Доклад: Как макросы изменили навигацию / Михаил Рубанов (Dodo Engineering)

Доклад: Как макросы изменили навигацию / Михаил Рубанов (Dodo Engineering)

Введение в навигацию Swift UI

Приветствие и представление

  • Всем привет, с вами подлодка iOS Крю. Мы находимся на четвёртом дне сезона номер 15, посвящённого Swift UI.
  • Ведущие: Никита Краснов и Женя Нофрейчик. Сегодня к нам присоединился Миша Рубанов для обсуждения навигации в Swift UI.

Знакомство с Мишей Рубановым

  • Миша Урбанов делится своим опытом работы в Додожниринге и рассказывает о своей книге по доступности iOS, которая стала популярной среди компаний.
  • Он упоминает, что сегодня будет обсуждаться работа команды Point Free и их вклад в развитие Swift UI через макросы.

Обсуждение макросов в Swift

Основные темы доклада

  • Доклад будет поверхностным, но с достаточным количеством примеров кода для понимания современных инструментов Swift и их применения в 2025 году.
  • Участники смогут ознакомиться с проблемами Swift и возможными решениями через использование макросов.

Проблемы навигации в Swift

  • Обсуждаются проблемы передачи данных между структурами и классами, а также сложности с различными модификаторами состояния (state).
  • Упоминается необходимость критики текущих подходов к навигации из-за исторически накопившихся проблем и недостатков производительности при использовании Combine.

Макросы как решение

Что такое макросы?

  • Макросы позволяют добавлять код на этапе компиляции, улучшая работу с данными без значительных затрат ресурсов во время выполнения программы.
  • Пример использования библиотеки Point Free CAS Possible для упрощения обращения к свойствам объектов показывает практическое применение макросов в разработке приложений на Swift UI.

Обсуждение возможностей Swift и макросов

Использование Enum в Swift

  • Обсуждается использование enum в различных функциях, таких как map, filter и reduce. Упоминается возможность создания обратного swash.id для получения нужного свойства.
  • Проблема с использованием enum заключается в том, что нельзя добавить дополнительные объекты к каждому значению, чтобы затем к ним обратиться.

Состояния экранов в SwiftUI

  • В SwiftUI часто требуется обрабатывать три состояния экрана: загрузка, получение данных или ошибка. Это создает необходимость передавать данные через enum.
  • Приводится пример навигационного маршрута с вводом телефона и SMS-кода для авторизации. Необходимость извлечения данных из enum для конкретных случаев (например, телефон или SMS).

Дублирование кода при работе с Enum

  • Для получения значений из enum необходимо повторять код для каждого случая, что приводит к дублированию и усложнению работы программиста.
  • Пример из проекта "Додопи", где типы заказов имеют одинаковые свойства, но требуют написания дублирующего кода.

Решение проблемы с помощью библиотеки Kсобов

  • Библиотека Kсобов предлагает макросы для упрощения работы с enum. Макрос позволяет использовать специальный синтаксис для извлечения значений без дублирования кода.
  • Возможность развернуть макросы показывает генерируемый код во время компиляции, что помогает понять структуру создаваемого кода.

Улучшение декларативности через макросы

  • Макросы позволяют описывать шаблонный код более декларативно, упрощая работу программистов и делая код более читабельным.
  • Появление новых возможностей в Swift 17 вместе с фреймворком observation улучшает работу со свойствами на уровне макросов.

Критика текущих подходов в SwiftUI

  • Обсуждаются недостатки текущей структуры SwiftUI: необходимость подписывать классы как observable object и каждое свойство как published.
  • Упоминается о несогласованности между различными объектами (state object, environment object), что затрудняет разработку.

Новшества фреймворка Observation

  • Apple представляет новый фреймворк observation, который упрощает процесс подписки на изменения объектов без необходимости использования лишних конструкций.
  • Сравнение старого подхода с новым показывает упрощение процесса объявления классов и их свойств благодаря использованию макросов.

Изменения в Swift UI и управление состоянием

Упрощение работы с паблишами

  • В новых версиях Swift UI больше не требуется подписывать различные паблиш свойства, что упрощает процесс разработки. Apple рекомендует удалять их из проекта.
  • Свойства теперь автоматически отслеживаются на изменения, благодаря макросам, которые делают это за разработчика.

Подписка на состояние

  • Вместо подписки на state object, теперь можно просто подписать state. Это делает код более понятным и уменьшает количество необходимых действий.
  • Если объект передается извне (например, в view-модель), его можно подписать через тип LED. Для объектов, созданных внутри вьюшки, необходимо создать стейт для хранения между перерисовками.

Новые концепции биндинга

  • Появилось новое слово — bindable, которое применяется ко всему классу. Это упрощает работу с изменениями значений внутри объекта.
  • Остальные элементы окружения остаются прежними; синтаксис стал проще и более согласованным между структурами и классами.

Проблемы совместимости

  • При поддержке старого кода на Swift GUI необходимо помнить о различных конструкциях и переключаться между ними при рефакторинге или миграции.

Обновления в Swift UI

  • Важно импортировать необходимые библиотеки для корректной работы новых функций. Некоторые импорты могут быть пропущены в документации.
  • Swift UI построен поверх Combine, но необходимость использования паблишеров значительно снизилась благодаря новым протоколам наблюдения.

Протокол наблюдения

  • Новый протокол observation tracking позволяет более точно отслеживать изменения свойств объектов без необходимости постоянного обращения к паблишерам.
  • Функция vis observation tracking имеет две замыкания: первое определяет свойства для отслеживания изменений, второе выполняется только при изменении этих свойств.

Оптимизация перерисовок

  • Теперь код может сам определять, какие свойства изменились и вызывать перерисовку только при необходимости. Это улучшает производительность приложения.
  • Если свойство не было затронуто в коде, то принт не вызовется, что позволяет избежать лишних операций и повышает эффективность работы интерфейса.

Обзор функции Observation в SwiftUI

Основные концепции и принципы

  • Боди вьюхи обернут в функцию Vis observation tracking, которая отвечает за перерисовку вьюшки при изменении значений. Это упрощает процесс, так как не нужно вручную управлять обновлениями.
  • Вьюха содержит список стран с состоянием (стейт), который включает названия и ссылки на флаги. Перерисовка происходит только при обращении к определённым свойствам во вью-модели.
  • Если изменяются свойства внутри модели, которые не используются во вьюшке, то перерисовка не произойдёт, что значительно оптимизирует производительность.

Эффективность и производительность

  • Переход на Observation может сократить количество перерисовок до двух раз по сравнению с предыдущими версиями SwiftUI, особенно на нагруженных экранах.
  • Однако использование новых функций требует версии Swift 5.7 или выше, что является значительным ограничением для разработчиков.

Проблемы и недостатки

  • Макросы могут увеличивать время компиляции из-за добавляемого кода. Это может стать проблемой для больших проектов.
  • Несмотря на преимущества, многие разработчики испытывают трудности с пониманием работы новых макросов и их влияния на код.

Упрощение разработки

  • Функция Observation позволяет упростить описание моделей данных, обеспечивая перерисовку только тех элементов интерфейса, которые действительно изменились.
  • Сложность понимания внутренней логики работы макросов может затруднить отладку кода и выявление ошибок.

Возможности бэкпортирования

  • Для использования функционала Observation можно применить сторонний фреймворк Perception от Pointf, который добавляет возможность отслеживания изменений свойств.
  • При использовании этого фреймворка можно расширять функциональность своих классов через добавление маркеров для отслеживания изменений.

Подробности реализации

  • При добавлении маркера к свойству автоматически создаются дополнительные механизмы для отслеживания его состояния и изменений.
  • Каждый раз при обращении к свойству регистрируется изменение его значения, что позволяет эффективно управлять состоянием интерфейса без лишних затрат ресурсов.

Работа с вью-моделью и изменениями

Принципы работы с регистрацией изменений

  • При записи значений из вью-модели происходит автоматическая регистрация изменений, что позволяет отслеживать изменения состояния.
  • Свойства, которые не должны учитываться при дальнейших изменениях, помечаются как perception ignored, что улучшает производительность.

Оптимизация работы с зависимостями

  • Внешние зависимости часто являются константами и могут быть помечены для игнорирования, чтобы избежать ненужной регистрации изменений.
  • Макросы автоматически добавляют геттеры и сеттеры к свойствам, упрощая процесс отслеживания изменений на уровне вью-модели.

Сравнение фреймворков

  • Синтаксис фреймворка perception отличается от предыдущих версий: например, observable стал perception, а bindableperception bindable.
  • Код фреймворка был бэкпортирован для использования в более ранних версиях iOS, сохраняя нативность кода Apple.

Реализация на уровне вьюшки

  • Для каждой вьюшки необходимо добавлять функцию vis perception tracking, что может усложнить разработку.
  • Использование макроса perceptable позволяет легко отслеживать изменения состояния без дополнительных подписок на уровне модели.

Проблемы и решения при использовании нового фреймворка

  • Необходимость добавления функции для каждой вьюшки может привести к ошибкам компиляции; иногда разработчики временно убирают эту функцию для устранения ошибок.
  • Автообнаружение пропущенной функции помогает выявить ошибки во время разработки без остановки выполнения приложения.

Обзор Perception Tracking в Swift

Введение в Perception Tracking

  • Обсуждение использования Visper perception tracking и его саморефлексирующих свойств. Упоминается, что добавление perceptable к описанию в view-модели упрощает процесс разработки.
  • Сравнение системного кода через макросы, которые позволяют создать нативную библиотеку. Упоминается возможность легкой миграции через автозамену.

Преимущества и недостатки

  • Перception tracking требует добавления к каждой вьюшке, что может замедлить компиляцию. Однако это жертва ради удобства разработки.
  • Необходимость добавления perception tracking во множество мест на экране, особенно при использовании сложных интерфейсов.

Автоматизация и предупреждения

  • Xcode автоматически подсказывает о пропущенных местах для добавления perception tracking, что снижает вероятность ошибок разработчика.
  • Обсуждение вопроса о том, почему Apple не реализовала некоторые функции, которые облегчили бы работу разработчиков.

Связь с другими фреймворками

  • Уточняется, что фреймворки observation и perception не связаны со Swift напрямую; они могут быть использованы для улучшения MVVM архитектуры.
  • Возможность бэкпортирования функционала в UI Kit для создания более эффективных моделей данных.

Итоговые мысли о разработке

  • Подчеркивается простота создания прототипов на Swift с использованием новых фреймворков и их универсальность между различными платформами.
  • Возможность тестирования функций на продакшене без необходимости полной переписки кода. Это создает гибкость в процессе разработки.
  • Заключение о том, что использование Perception и Swift Navigation может упростить будущую миграцию на SwiftUI благодаря стабильной архитектуре приложения.

Обсуждение фреймворка Perception в iOS 17

Введение в Perception и его статус

  • Фреймворк Perception был представлен с выходом iOS 17, что произошло довольно быстро после анонса на WB DC.
  • На момент выхода iOS 17 фреймворк уже работал, хотя изначально его использование вызывало сомнения из-за возможных багов.
  • Обсуждения в репозиториях показывают наличие багов, но они связаны с эпловыми Swift-фреймворками, а не с нативным Swift.

Проблемы навигации в приложениях

  • Рассматривается пример приложения Todoist и необходимость создания модальных состояний для добавления, редактирования и удаления задач.
  • Для каждого действия требуется отдельное модальное окно, что усложняет структуру кода при использовании нативного Swift UI.
  • Код становится сложным для тестирования из-за неопределённого поведения при одновременном вызове нескольких свойств.

Решение через использование enum

  • Проблема неопределённого поведения может быть решена с помощью использования enum для описания возможных состояний интерфейса.
  • Enum позволяет четко определить одно состояние из нескольких вариантов, что упрощает логику навигации и улучшает тестирование.

Интеграция нового подхода

  • Новый фреймворк case possible позволяет использовать макросы для более удобной работы с состояниями интерфейса.
  • Теперь можно обращаться к единственному значению состояния на уровне view-модели, что упрощает код и делает его более предсказуемым.

Заключение о новых возможностях

  • Изменения позволяют более эффективно управлять состояниями интерфейса и передавать данные между компонентами приложения.
  • Это приводит к улучшению качества кода и облегчению процесса разработки благодаря ясности логики навигации.

Обсуждение изменений в архитектуре приложений

Применение новых подходов к свойствам

  • Ранее свойства использовались напрямую, теперь они обрабатываются через view модели, что позволяет избежать неоднозначности в коде.
  • Это упрощает написание автотестов, так как тесты становятся однозначными и не могут показывать зеленый статус при наличии ошибок в UI.

Улучшение интеграционных тестов

  • Связывание свойств в view моделях делает интеграционные тесты более понятными и предсказуемыми.
  • В UIKit также применяются аналогичные конструкции для создания UI-контроллеров с дополнительными обертками.

Синтаксис и привязка данных

  • В view моделях можно указывать, какие экраны нужно отображать на основе привязки данных.
  • SwiftUI вводит конструкцию @Bindable, которая позволяет отслеживать изменения значений в модели при взаимодействии пользователя с интерфейсом.

Обзор фреймворков и их особенностей

  • Фреймворк observation добавляет возможность связывать данные между UI и моделью, что упрощает разработку.
  • Конструкции остаются простыми: достаточно указать контроллер для отображения нужного состояния интерфейса.

Навигация между SwiftUI и UIKit

  • Синтаксис навигации становится схожим между SwiftUI и UIKit благодаря библиотекам pointfree.
  • Разработчики обсуждают необходимость улучшения миграции между этими фреймворками для повышения удобства работы.

Проблемы онбординга в приложениях

Сложности процесса онбординга

  • Онбординг включает множество шагов: ввод телефона, подтверждение по SMS, создание пароля и другие проверки.
  • Необходимость проходить все этапы каждый раз вызывает желание автоматизировать процесс тестирования.

Архитектурные подходы к автотестам и навигации в приложениях

Обсуждение архитектуры автотестов

  • В начале обсуждения автор делится своими целями относительно архитектуры автотестов, акцентируя внимание на сценарии взаимодействия пользователя с приложением.
  • Основные шаги включают запрос SMS, подтверждение, создание паскода и проверку статуса пользователя (новый или старый).
  • Каждый экран приложения представлен отдельной вью-моделью, что позволяет декомпозировать сценарий на более мелкие части для удобства тестирования.

Декомпозиция сценариев

  • Автор подчеркивает важность декомпозиции сценария на экраны и возможность пересборки элементов интерфейса.
  • Навигация осуществляется через стек моделей, где каждая вью-модель сопоставляется с соответствующей вьюшкой для отображения.

Универсальная навигация между фреймворками

  • Обсуждается необходимость отделить данные от визуальных компонентов, чтобы обеспечить универсальность навигации между различными фреймворками.
  • Автор планирует создать перечень экранов с их логикой и описать переходы между ними для упрощения тестирования.

Тестирование навигационных сценариев

  • Начало теста включает проверку наличия значений внутри массива навигации, что является критерием успешного выполнения сценария.
  • Если значение добавлено в массив, это означает успешное выполнение навигации; если нет — тест не проходит.

Проверка состояния и завершение теста

  • Автор описывает процесс проверки экрана телефона и последующих экранов (SMS и паскод), используя вспомогательные функции для управления состоянием.
  • Завершение теста включает проверку всех этапов онбординга и маршрута навигационного стека. Это демонстрирует простоту написания кода при наличии хорошо структурированных функций.

Обсуждение навигации в Swift UI

Проблемы с навигацией во время онбординга

  • Во время онбординга кнопки "назад" должны исчезать, если пользователь уже заполнил данные. Это улучшает пользовательский опыт и предотвращает возврат на предыдущие экраны.
  • Исследование темы и подготовка к новому проекту привели к созданию теста, который демонстрирует архитектурные схемы и подходы к запросам.

Архитектура и декомпозиция

  • Декомпозиция включает создание вьюмоделей, которые описывают необходимые экраны и запросы через TDD (разработка через тестирование).
  • Использование стандартного Swift UI для работы с Navigation Stack позволяет легко управлять переходами между экранами.

Работа с данными и вьюмоделями

  • Важно отделить логику данных от интерфейса, чтобы упростить поддержку проекта. Это позволяет добавлять новые экраны без значительных изменений в коде.
  • Перception tracking необходимо обернуть для отслеживания состояния навигации. Это может привести к частым вызовам функции.

Автоматизация тестирования

  • Автотесты помогают проверить целостность диаграммы переходов между экранами, что упрощает процесс разработки.
  • При добавлении нового экрана компилятор подсвечивает все места, где нужно обновить значения, что минимизирует ошибки.

Сравнение с UIKit

  • Swift Navigation предоставляет дополнительную обертку над UI Navigation Controller для использования начиная с iOS 13.
  • Код на уровне UIKit можно адаптировать под Swift UI, сохраняя гибкость при работе с различными компонентами интерфейса.

Гибкость разработки

  • Возможность комбинировать элементы из UIKit и Swift UI дает разработчикам свободу выбора подходящих инструментов для реализации проектов.
  • Библиотека предлагает возможность уменьшения рисков при миграции между различными версиями фреймворков.

Модель универсальной навигации и её тестирование

Основные аспекты работы модели

  • Модель универсальной навигации эффективно тестируется, позволяя легко извлекать данные. Она функционирует на основе observation или perception.
  • При повышении минимальных требований, места использования perception выделяются предупреждениями, что указывает на необходимость их удаления.

Проблемы и баги в фреймворках

  • Обсуждаются различные проблемы (ишью), многие из которых являются багами внутри используемого кита. Эти же баги могут проявляться при использовании нативных фреймворков.

Структура тестирования сценариев

  • Важным аспектом является разделение доменной логики и сценариев от пользовательского интерфейса (UI). UI состоит из экранов с ю-моделями и сценариев переходов между экранами.
  • Навигация между экранами не представляет сложности, так как она управляется через вью-модельки.

Универсальность тестирования

  • Верхняя часть схемы может быть отделена для создания универсального решения между различными фреймворками. Это позволяет писать сквозные тесты для проверки бизнес-кейсов.
  • Предпочтение отдается верхнеуровневым тестам, которые охватывают основные функциональные возможности приложения.

Гибкость разработки и использование новых технологий

Возможности выбора фреймворка

  • Разработчики имеют свободу выбора фреймворка для верстки: Swift, Kit или другие варианты. Это делает процесс более гибким.

Вопрос о поддержке Apple

  • Обсуждается вопрос, почему Apple не реализовала некоторые функции самостоятельно, что могло бы упростить разработку приложений.

Использование макросов и их влияние на проект

  • Макросы добавляют дополнительный код в проект, что может увеличить время компиляции. Однако для проектов среднего размера это может быть приемлемо.

Новые технологии и их применение

Фреймворки для упрощения разработки

  • Case Possible - полезный фреймворк для извлечения значений без необходимости написания большого количества кода.
  • Sun Framework Observation работает только с iOS 17, но предоставляет возможность использовать perception как бэкпорт.

Автотестирование и производительность

  • Swift Navigation предлагает модель навигации с возможностью интеграции диплинков и обработки пушей. Это также позволяет писать автотесты.

Будущее разработки приложений

Поддержка старых версий iOS

  • Ключевые фреймворки теперь можно использовать на iOS 13 благодаря последней версии Swift. Это открывает новые возможности для разработчиков.

Переход к новым архитектурным решениям

  • Разработчики могут готовить свою архитектуру под UIKit с перспективой перехода на более современные технологии.

Личный опыт разработчика

  • Докладчик делится своим опытом смены работы и намерением разрабатывать новое приложение в банковской сфере с использованием обсуждаемых технологий.

Заключение доклада

Итоги обсуждения

  • Доклад завершен призывом подписаться на канал для получения обновлений о процессе разработки нового приложения.

Введение в вопросы команды

  • Миша делится, что команда накопила 11 вопросов по поводу разработки и архитектуры. Он предлагает начать с первого вопроса о TCA в Doda.

Использование TCA в Doda

  • Ответ на первый вопрос: TCA (The Composable Architecture) не используется в Doda. Это важно, так как обсужденный фреймворк Point не связан с TCA.
  • Mиша отмечает, что он не использует TCA ни в одном проекте из-за недовольства идеей создания проекта вокруг одного фреймворка, который может упростить работу.
  • Он упоминает свой опыт работы с различными фреймворками за 12 лет и предостерегает от их использования без критического анализа.
  • Несмотря на это, он следит за инструментами от Point и считает их полезными для развития Swift-программирования.

Архитектурные рекомендации Apple

  • Обсуждается необходимость извлечения модели: Apple рекомендует передавать её через environment, но это может привести к проблемам с тестированием проекта.
  • Mиша подчеркивает важность архитектуры для возможности тестирования различных сценариев приложения, включая навигацию и взаимодействие с UI-компонентами.

Проблемы при передаче view-моделей

  • Упоминается риск коллизий при передаче view-моделей между экранами: возможны проблемы с обновлением данных или даже сбои интерфейса приложения.
  • Обсуждаются потенциальные баги, возникающие из-за неправильного управления состоянием объектов во время передачи между представлениями.

Заключение

  • Вопросы о влиянии макросов на время сборки остаются открытыми; дальнейшие обсуждения планируются по этой теме.

Обсуждение макросов в Swift

Введение в использование макросов

  • Обсуждается зависимость эффективности использования макросов от частоты их применения. Приведен пример с коллегой, который создает Telegram-канал для описания нового макроса memberwise init.

Автоматизация создания конструкторов

  • Макрос memberwise init позволяет автоматически генерировать конструкторы для моделей, что упрощает процесс разработки и уменьшает необходимость ручного написания кода.

Влияние на время сборки проекта

  • Упоминается, что использование макросов может увеличить время компиляции проекта из-за дополнительных операций, связанных с компиляцией Swift-кода.

Сравнение производительности

  • Отмечается отсутствие конкретных данных о замедлении при использовании новых возможностей Swift. Однако есть синтетические тесты, показывающие значительное замедление (в сотни раз) при использовании некоторых фреймворков.

Бизнес-подход к разработке

  • Обсуждается подход бизнеса к скорости разработки: в условиях стартапа скорость компиляции может быть менее важной по сравнению с необходимостью быстрого выхода на рынок.

Тестирование анимаций в навигации

Анимация и её тестирование

  • Задан вопрос о том, как протестировать анимацию в навигации. Уточняется необходимость проверки флага анимации и того, как она работает во время переходов между экранами.

Функциональность Swift UI

  • Рассматривается функция V animation в Swift UI для изменения значений с анимацией и возможность создания транзакций без анимаций для мгновенного отображения экранов.

Проблемы с тестированием UI

  • Подчеркивается сложность тестирования конкретных сценариев без анимации. Неясно, как можно проверить это через юайные тесты.

Заключение обсуждения

  • Завершение записи обсуждения. Участники выражают благодарность зрителям за внимание и предлагают продолжить общение по оставшимся вопросам.
Video description

В Свифте появились макросы, что дало возможность упростить и спрятать шаблонный код, а значит сделать наш код более верхнеуровневым. Так Apple использовала макросы во фреймворке Observation, чтобы упростить SwiftUI, а Point-Free сделала библиотеку, которая позволяет использовать Observation начиная с iOS 13. Еще это позволило использовать Observation вместе с UIKit, что дает нам «нормальный» MVVM и более того — модель данных может быть универсальной между разными UI-фреймворками. Ну и в конце это дало возможность написать универсальную навигацию, которая решает часть задача за нас и которую легко тестировать. Посмотрим на фреймворки CasePathable, Observation, Perception и SwiftNavigation Контакты спикера: https://t.me/akaDuality https://t.me/RubanovMobile Понравилось видео и хочешь узнать что-то еще про Podlodka iOS Crew? Забирай весь плейлист на https://podlodka.io/crew-records или покупай годовой доступ ко всей Библиотеке контента.