Доклад: Как макросы изменили навигацию / Михаил Рубанов (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, аbindable—perception 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
- Подчеркивается сложность тестирования конкретных сценариев без анимации. Неясно, как можно проверить это через юайные тесты.
Заключение обсуждения
- Завершение записи обсуждения. Участники выражают благодарность зрителям за внимание и предлагают продолжить общение по оставшимся вопросам.