Как обновлять схемы SwiftData и не ломать данные после релиза
После обновления iOS-приложение открывает существующее хранилище. Поэтому даже первую модель автор советует выпускать через
SwiftData сама переносит данные при лёгких изменениях, например при добавлении необязательного свойства. Новое обязательное поле без значения, смена типа или объединение сущностей требуют ручного преобразования через
Разбор миграций SwiftData объясняет, как учитывать пользователей, которые пропускают версии приложения, и когда нужны промежуточные схемы. Проверяйте переход с реального хранилища на диске: значение по умолчанию в Swift-инициализаторе не гарантирует заполнение старых записей.
После обновления iOS-приложение открывает существующее хранилище. Поэтому даже первую модель автор советует выпускать через
VersionedSchema: она станет исходной точкой для следующих версий.SwiftData сама переносит данные при лёгких изменениях, например при добавлении необязательного свойства. Новое обязательное поле без значения, смена типа или объединение сущностей требуют ручного преобразования через
SchemaMigrationPlan и MigrationStage.Разбор миграций SwiftData объясняет, как учитывать пользователей, которые пропускают версии приложения, и когда нужны промежуточные схемы. Проверяйте переход с реального хранилища на диске: значение по умолчанию в Swift-инициализаторе не гарантирует заполнение старых записей.
👍1
Как добавить свайп-действия в Android без устаревшего API
В Compose Material 3 компонент
Состояние создаётся через
Пошаговый пример с кодом рассчитан на Material 3 1.4.0 и 1.5.0-alpha11. Если в проекте другая версия библиотеки, перед внедрением сверьте сигнатуры API.
В Compose Material 3 компонент
SwipeToDismissBox позволяет назначить разные действия для свайпов влево и вправо. В примере элемент списка после одного жеста помечается прочитанным, после другого удаляется.Состояние создаётся через
rememberSwipeToDismissBoxState без устаревшего confirmValueChange. Направление жеста обрабатывается в колбэке компонента, а reset() возвращает элемент на место перед отметкой прочитанного. Фон меняет цвет и значок в зависимости от направления и хода свайпа. Для элементов списка используются стабильные ключи, чтобы состояние не переезжало между строками.Пошаговый пример с кодом рассчитан на Material 3 1.4.0 и 1.5.0-alpha11. Если в проекте другая версия библиотеки, перед внедрением сверьте сигнатуры API.
🔥1💯1
Как показывать ответ Foundation Models в iOS по мере генерации
В Swift метод
Макрос
Разбор потоковой генерации также показывает
В Swift метод
respond возвращает результат после завершения генерации. Для постепенного обновления интерфейса можно вызвать streamResponse: он создаёт ResponseStream, который перебирается через for try await и выдаёт частичные версии объекта.Макрос
@Generable добавляет тип PartiallyGenerated с необязательными свойствами. Модель заполняет поля в порядке объявления, поэтому заголовок, текст и подсказки стоит выводить в той же последовательности.Разбор потоковой генерации также показывает
collect(): после перебора потока метод возвращает итоговый структурированный объект.❤1
Как перевести платное iOS-приложение на freemium и сохранить доступ покупателям
Схема миграции через StoreKit опирается на
В TestFlight и среде ревью исходная версия всегда «1.0», а в production приходит номер сборки: сравнивайте номера сборок. Для отладки добавьте ручное переключение статуса, иначе ревьюер не увидит покупку.
После переустановки исходная версия меняется на текущую. Для одного устройства статус храните в Keychain, для нескольких понадобится CloudKit или сервер.
Схема миграции через StoreKit опирается на
AppTransaction: исходная версия и дата покупки помогают распознать тех, кто установил приложение до перехода. Им можно выдать пожизненный доступ.В TestFlight и среде ревью исходная версия всегда «1.0», а в production приходит номер сборки: сравнивайте номера сборок. Для отладки добавьте ручное переключение статуса, иначе ревьюер не увидит покупку.
После переустановки исходная версия меняется на текущую. Для одного устройства статус храните в Keychain, для нескольких понадобится CloudKit или сервер.
👍1
Как Baseline Profiles ускоряют запуск и прокрутку Android-приложений
ART сначала интерпретирует байткод Kotlin и Java, а затем компилирует часто вызываемые методы. Baseline Profile заранее задаёт нужные классы и методы: с Android 9 ART компилирует их при установке приложения.
Meta собирает последовательности загрузки классов для запуска, прокрутки ленты и открытия фото. По данным компании, профили улучшили отдельные ключевые метрики до 40%.
Опыт Meta с Baseline Profiles показывает, как ускорять не только холодный запуск.
ART сначала интерпретирует байткод Kotlin и Java, а затем компилирует часто вызываемые методы. Baseline Profile заранее задаёт нужные классы и методы: с Android 9 ART компилирует их при установке приложения.
Meta собирает последовательности загрузки классов для запуска, прокрутки ленты и открытия фото. По данным компании, профили улучшили отдельные ключевые метрики до 40%.
Опыт Meta с Baseline Profiles показывает, как ускорять не только холодный запуск.
👍2🎉2
Как собрать фильтры и индикаторы в Android на Compose Material 3
В Compose Material 3 есть готовые компоненты для интерфейсов, которые часто собирают вручную.
Для фильтра по цене подойдёт
Примеры компонентов с кодом подходят для Material 3 версий 1.3.2, 1.4.0-beta02 и 1.5.0-alpha04: используемый API между ними не менялся.
В Compose Material 3 есть готовые компоненты для интерфейсов, которые часто собирают вручную.
TriStateCheckbox связывает общий флажок с дочерними: показывает, выбраны все пункты, ни одного или только часть. SegmentedButton позволяет выбрать один или несколько вариантов из двух-пяти.Для фильтра по цене подойдёт
RangeSlider, а BadgedBox поможет оформить индикатор непрочитанных уведомлений. При переносе примера с ползунком проверьте начальную границу диапазона: её нужно исправить. Параметр steps задаёт количество промежуточных значений, а не общее число позиций.Примеры компонентов с кодом подходят для Material 3 версий 1.3.2, 1.4.0-beta02 и 1.5.0-alpha04: используемый API между ними не менялся.
Как передавать контент между iOS-приложениями через Siri
Чтобы Siri могла отдать сущность другому приложению, AppEntity представляют системным типом. В примере ContactEntity содержит IntentPerson, реализует Transferable и передаёт свойство через IntentValueRepresentation. Так система получает значение для обмена.
При импорте IntentValueQuery ищет сохранённый контакт по имени, телефону, адресу почты или ID. Пустой результат запускает importing-замыкание: оно создаёт новую сущность и сохраняет контакт. Правила сопоставления остаются в приложении.
Разбор передачи контента через App Intents содержит Swift-код обоих направлений. Минимальная версия iOS и требования SDK не указаны, поэтому совместимость нужно отдельно сверить с документацией Apple.
Чтобы Siri могла отдать сущность другому приложению, AppEntity представляют системным типом. В примере ContactEntity содержит IntentPerson, реализует Transferable и передаёт свойство через IntentValueRepresentation. Так система получает значение для обмена.
При импорте IntentValueQuery ищет сохранённый контакт по имени, телефону, адресу почты или ID. Пустой результат запускает importing-замыкание: оно создаёт новую сущность и сохраняет контакт. Правила сопоставления остаются в приложении.
Разбор передачи контента через App Intents содержит Swift-код обоих направлений. Минимальная версия iOS и требования SDK не указаны, поэтому совместимость нужно отдельно сверить с документацией Apple.
❤1👍1
Как встроить генерацию изображений через Image Playground в iOS-приложение
Фреймворк Image Playground позволяет создавать изображения в Swift из текста, фотографии, рисунка PencilKit или большого текстового фрагмента. За генерацию отвечает
Доступны стили animation, illustration и sketch, но конкретный набор зависит от устройства. Перед вызовом стоит проверить
Примеры на Swift показывают, как передать текст вместе с исходной картинкой и получить
Фреймворк Image Playground позволяет создавать изображения в Swift из текста, фотографии, рисунка PencilKit или большого текстового фрагмента. За генерацию отвечает
ImageCreator: метод images получает описание, стиль и число результатов, а затем возвращает их по одному через AsyncSequence.Доступны стили animation, illustration и sketch, но конкретный набор зависит от устройства. Перед вызовом стоит проверить
availableStyles; создание ImageCreator может завершиться ошибкой, если устройство не поддерживает генерацию. За один запрос система выдаёт не больше четырёх изображений.Примеры на Swift показывают, как передать текст вместе с исходной картинкой и получить
CGImage. Минимальную версию ОС и список совместимых устройств статья не называет, поэтому их нужно проверить отдельно перед внедрением.Как загружать локальный HTML в SwiftUI WebView через свою URL-схему
В iOS 26 у SwiftUI появились WebView и WebPage, а собственная URL-схема позволяет загружать локальные ресурсы. Например, приложение может открыть
Обработчик URLSchemeHandler получает запрос, проверяет схему, находит файл, определяет MIME-тип и читает данные. Затем он последовательно передаёт в асинхронный поток URLResponse и содержимое файла, а при ошибке завершает поток с исключением.
Обработчик регистрируется в WebPage.Configuration, созданная WebPage передаётся в WebView, а загрузка запускается через
В iOS 26 у SwiftUI появились WebView и WebPage, а собственная URL-схема позволяет загружать локальные ресурсы. Например, приложение может открыть
quotes://001.html, найти файл в основном пакете и показать страницу без сервера.Обработчик URLSchemeHandler получает запрос, проверяет схему, находит файл, определяет MIME-тип и читает данные. Затем он последовательно передаёт в асинхронный поток URLResponse и содержимое файла, а при ошибке завершает поток с исключением.
Обработчик регистрируется в WebPage.Configuration, созданная WebPage передаётся в WebView, а загрузка запускается через
page.load. Метод возвращает события, по которым можно отслеживать ход загрузки. Перед внедрением проверьте минимальную версию приложения: этот API доступен начиная с iOS 26.Как ускорить первый кадр камеры в iOS 26 с AVFoundation
Apple предлагает разделить запуск камеры: сначала создать превью и кнопку затвора, а остальные элементы интерфейса и выходы захвата инициализировать позже. В докладе о быстром запуске камеры Deferred Start сократил ожидание превью примерно вдвое.
AVCaptureSession, startRunning и stopRunning блокируют поток, поэтому их не стоит вызывать в главном потоке. Конфигурацию применяют один раз, а при Deferred Start откладывают все выходы, кроме превью.
API доступен с iOS 26. При сборке с SDK iOS 26 автоматический режим включён по умолчанию. Первый кадр появится раньше, но фотосъёмка не ускорится, пока не готов её выход.
Apple предлагает разделить запуск камеры: сначала создать превью и кнопку затвора, а остальные элементы интерфейса и выходы захвата инициализировать позже. В докладе о быстром запуске камеры Deferred Start сократил ожидание превью примерно вдвое.
AVCaptureSession, startRunning и stopRunning блокируют поток, поэтому их не стоит вызывать в главном потоке. Конфигурацию применяют один раз, а при Deferred Start откладывают все выходы, кроме превью.
API доступен с iOS 26. При сборке с SDK iOS 26 автоматический режим включён по умолчанию. Первый кадр появится раньше, но фотосъёмка не ускорится, пока не готов её выход.
Как связать список и экран деталей анимацией в Jetpack Compose
Схема интеграции с Navigation Compose:
Для одного изображения подходит
Длительность лучше держать в пределах 300–400 мс и учитывать системное отключение анимаций.
Схема интеграции с Navigation Compose:
SharedTransitionLayout размещают над NavHost, а элементам списка и экрана деталей задают одинаковый ключ по ID. Compose сопоставляет их и анимирует положение и размер.Для одного изображения подходит
sharedElement, для карточки с меняющимся содержимым — sharedBounds. Не используйте индекс списка как ключ: после перестановки элементы могут связаться неверно.Длительность лучше держать в пределах 300–400 мс и учитывать системное отключение анимаций.
Как тестировать App Intents и Spotlight без автоматизации интерфейса
На WWDC26 Apple показала AppIntentsTesting для интеграционных тестов App Intents в iOS. Проверки запускают интенты на устройстве через тот же стек, что Siri, Shortcuts и Spotlight, но не зависят от интерфейса приложения или системы.
Тесты живут в обычном пакете XCUITest и обращаются к приложению по идентификатору пакета. Можно выполнить интент, проверить результат, прогнать запрос сущностей, связать несколько интентов и проверить индексацию Spotlight. Код приложения импортировать не нужно; приложение и средство запуска тестов должны использовать одну команду разработчика в настройках подписи.
В докладе с примерами кода также разбирают подготовку тестовых данных и запуск проверок в CI. Так регрессии интеграций с Siri и Shortcuts можно ловить без ручной проверки интерфейса.
На WWDC26 Apple показала AppIntentsTesting для интеграционных тестов App Intents в iOS. Проверки запускают интенты на устройстве через тот же стек, что Siri, Shortcuts и Spotlight, но не зависят от интерфейса приложения или системы.
Тесты живут в обычном пакете XCUITest и обращаются к приложению по идентификатору пакета. Можно выполнить интент, проверить результат, прогнать запрос сущностей, связать несколько интентов и проверить индексацию Spotlight. Код приложения импортировать не нужно; приложение и средство запуска тестов должны использовать одну команду разработчика в настройках подписи.
В докладе с примерами кода также разбирают подготовку тестовых данных и запуск проверок в CI. Так регрессии интеграций с Siri и Shortcuts можно ловить без ручной проверки интерфейса.
❤1
Когда SubcomposeLayout в Jetpack Compose оправдывает свою цену
Обычный
Он нужен, когда размер определяет состав интерфейса: например, строка тегов создаёт элементы до границы экрана и добавляет счётчик скрытых.
В разборе механики и DynamicChipRow показано, почему для расчёта одних размеров обычно достаточно
Обычный
Layout измеряет и размещает готовое дерево. SubcomposeLayout создаёт компоненты во время измерения, когда уже известны ограничения родителя, поэтому обходится дороже.Он нужен, когда размер определяет состав интерфейса: например, строка тегов создаёт элементы до границы экрана и добавляет счётчик скрытых.
В разборе механики и DynamicChipRow показано, почему для расчёта одних размеров обычно достаточно
Layout.Как сделать прокрутку LazyVStack в SwiftUI предсказуемее
Для длинной ленты в iOS полезны три правила: задавать предсказуемую высоту строк с переменным текстом; не сдвигать анимацией невидимые элементы в область экрана; отслеживать появление строк через
Apple подробно разбирает оценку размеров, загрузку представлений, предзагрузку и программную прокрутку. Доклад рассчитан на разработчиков, уже знакомых с компоновкой стеков в SwiftUI.
LazyVStack не строит весь список сразу: он загружает элементы у видимой области, а размеры строк за экраном оценивает по уже размещённым. Когда реальные размеры отличаются, стек уточняет общую высоту и смещение ScrollView. Поэтому логика, привязанная к абсолютному смещению, может срабатывать в разных местах.Для длинной ленты в iOS полезны три правила: задавать предсказуемую высоту строк с переменным текстом; не сдвигать анимацией невидимые элементы в область экрана; отслеживать появление строк через
onScrollTargetVisibilityChange, а не по абсолютному смещению.Apple подробно разбирает оценку размеров, загрузку представлений, предзагрузку и программную прокрутку. Доклад рассчитан на разработчиков, уже знакомых с компоновкой стеков в SwiftUI.