Вступление
Виджеты на iOS — не просто украшение, а необходимость для быстрого доступа к данным. Однако разработка сталкивается с рядом технических ограничений: TimelineProvider, бюджет фоновых обновлений (около 40–70 раз в день) и синхронизация через App Groups. Наши инженеры решали задачи обновления курса валют каждые 15 минут в WidgetKit, работали с интерактивными виджетами до того, как это стало мейнстримом. Если вам нужно показать данные на домашнем экране или экране блокировки, мы подберем оптимальное решение.
Перед началом разработки важно понять, какой механизм использовать: Today Extension (legacy) или WidgetKit. WidgetKit — рекомендованный Apple путь, но иногда требуется обратная совместимость. Мы поможем определиться.
Как работает WidgetKit?
WidgetKit — это не классический View с живым кодом, а набор заранее отрендеренных снимков (снапшотов). Вы реализуете TimelineProvider, который возвращает массив TimelineEntry. Каждый entry содержит дату показа и данные. Система рендерит SwiftUI View для каждого entry заранее и переключает их по расписанию.
Обновление виджета. WidgetCenter.shared.reloadTimelines(ofKind:) вызывается из основного приложения или Background App Refresh. Бюджет фоновых обновлений ограничен (примерно 40–70 раз в день). Если TimelineProvider запрашивает обновление слишком часто через TimelineReloadPolicy.after(Date), система может игнорировать запросы.
Почему стоит выбрать WidgetKit вместо Today Extension?
| Характеристика |
Today Extension |
WidgetKit |
| Целевое место |
Центр уведомлений |
Домашний экран, экран блокировки, Apple Watch |
| Технология |
UIKit |
SwiftUI |
| Интерактивность |
Нет |
Да (AppIntents с последних версий iOS) |
| Обновление |
NCWidgetProviding |
TimelineProvider + WidgetCenter |
| Размеры |
Фиксированный/расширенный |
Несколько фиксированных размеров |
| Поддержка Apple |
Legacy |
Активная |
WidgetKit лучше масштабируется и поддерживает современные фичи, такие как интерактивность и виджеты на экране блокировки.
Как реализовать WidgetKit?
- Создайте новый target типа Widget Extension.
- Реализуйте TimelineProvider: определите структуру Entry (данные) и методы getTimeline и placeholder.
- Напишите SwiftUI View для виджета, используя семейства (systemSmall, systemMedium и т.д.).
- Настройте App Group для обмена данными с основным приложением.
- Протестируйте в симуляторе и на реальном устройстве.
Интерактивность через AppIntents
В последних версиях iOS виджеты стали интерактивными. Используйте структуру, соответствующую AppIntent, с @MainActor. В SwiftUI виджета код: Button(intent: MyIntent()). Ограничения: нельзя показывать Alert или Sheet. Для сложных действий — глубокие ссылки через widgetURL().
App Group: обмен данными
Виджет — отдельный Extension process. Данные основного приложения напрямую недоступны. Используйте UserDefaults(suiteName:) для малых данных и FileManager.containerURL(forSecurityApplicationGroupIdentifier:) для файлов. Не храните данные виджета в папке Documents основного приложения — виджет их не увидит. Подробнее об App Groups читайте в документации Apple.
Подробнее о бюджете обновлений
Система выделяет каждому приложению квоту на фоновые обновления, которая зависит от времени суток и активности пользователя. В среднем виджет может обновляться 40–70 раз в день. Чтобы не исчерпать бюджет, используйте `TimelineReloadPolicy.atEnd` и не устанавливайте слишком частые даты обновлений.
Размеры и экран блокировки
WidgetKit поддерживает: systemSmall, systemMedium, systemLarge, systemExtraLarge (iPad). Начиная с последних версий iOS: accessoryCircular, accessoryRectangular, accessoryInline для экрана блокировки и Apple Watch. Виджет блокировки рендерится в grayscale в ambient режиме — дизайн должен быть читаемым в обоих режимах.
Today Extension (legacy)
NCWidgetProviding.widgetPerformUpdate(completionHandler:) — точка обновления. Extension должен вызвать completionHandler(.newData) или .noData в течение 30 секунд. Использует UIKit, без SwiftUI. Размер: компактный или расширенный через preferredContentSize.
Что входит в разработку виджета
- Анализ требований и выбор подходящего механизма (WidgetKit или Today Extension).
- Проектирование данных и взаимодействия с основным приложением.
- Реализация TimelineProvider и SwiftUI View для всех целевых размеров.
- Настройка App Group и обмена данными.
- Интеграция интерактивности (AppIntents) при необходимости.
- Настройка фоновых обновлений и бюджетов.
- Тестирование на реальных устройствах с разными версиями iOS.
- Публикация в App Store Connect и настройка TestFlight.
Наш опыт и гарантии
Мы — команда с 5+ годами опыта в iOS-разработке, реализовали более 20 проектов с виджетами, включая сложные кейсы с обновлением данных в реальном времени. Гарантируем качество кода, соблюдение App Store Review Guidelines и поддержку после релиза. WidgetKit — наш основной инструмент.
Сроки разработки
| Тип виджета |
Срок |
| WidgetKit (один размер, статичные данные) |
2–3 недели |
| WidgetKit (несколько размеров, интерактивность, экран блокировки) |
4–7 недель |
| Today Extension (legacy) |
2–4 недели |
Стоимость рассчитывается индивидуально после анализа ваших данных и частоты обновления. Получите консультацию — оценим ваш проект за 2 дня. Свяжитесь с нами, чтобы обсудить детали. Закажите разработку виджета уже сегодня и получите быстрый старт.
Разработка виджетов, App Clips и Live Activities: точки входа вне приложения
Мы знаем, что пользователь видит приложение не только внутри него. Виджет на домашнем экране, живой счёт матча в Dynamic Island, мини‑опыт без установки — всё это отдельные точки входа, которые мы реализуем с учётом ограничений платформы. За 5 лет мы разработали более 50 расширений для мобильных приложений — от простых информационных виджетов до App Clips с платёжными сценариями, экономя клиентам до 30% времени на повторных входах.
Разработка виджетов WidgetKit: почему нельзя просто «добавить виджет»
WidgetKit работает через Timeline Provider — виджет не живёт в памяти постоянно, а запрашивает снимки данных заранее. Самая частая ошибка: разработчик пытается показать данные в реальном времени через URLSession прямо из getTimeline(). Apple этого не запрещает, но при агрессивном обновлении система начинает троттлить запросы, и виджет зависает на устаревших данных.
Правильный подход: основное приложение обновляет данные через WidgetCenter.shared.reloadTimelines(ofKind:) — после получения пуш-уведомления или при возврате пользователя в foreground. Виджет читает данные из shared App Group container через UserDefaults(suiteName:) или файлового хранилища. Никаких прямых сетевых запросов в провайдере в продакшне.
В новейших версиях iOS появился AppIntent-based interactive widget — кнопки и тогглы прямо на виджете без открытия приложения. Реализуется через Button(intent:) в SwiftUI-разметке виджета. Работает только для простых действий; сложная логика должна переходить в приложение через widgetURL.
Как Live Activities меняют пользовательский опыт?
Live Activities — механизм для отображения живых данных на Lock Screen и в Dynamic Island (iPhone 14 Pro+). Запускаются через ActivityKit, обновляются через push-уведомления типа liveactivity с полезной нагрузкой до 4KB.
Архитектурно это отдельный SwiftUI-таргет с двумя представлениями: компактным (Dynamic Island) и развёрнутым (Lock Screen). Данные передаются через ActivityAttributes — строго типизированную структуру. Динамическая часть — ContentState, статическая (не меняется за время активности) — в ActivityAttributes напрямую.
Типичная проблема: Live Activity не обновляется на устройстве, хотя push отправляется. Причина — приложение не имеет permission на background push или apns-push-type выставлен неправильно. В production нужен apns-push-type: liveactivity и токен из activity.pushToken. Согласно документации Apple, без корректного push-токена Activity не получит обновлений.
Когда использовать App Clips, а когда Instant Apps?
App Clips (iOS) и Instant Apps (Android) решают похожую задачу — дать пользователю функциональность без установки полного приложения. Но реализация принципиально разная.
App Clip — отдельный таргет в Xcode, максимум 15MB, запускается через NFC-метку, QR-код, Safari Smart App Banner или ссылку в Messages. Доступ к данным ограничен: нет Keychain sharing с основным приложением без явной настройки, нет доступа к HealthKit, нет push-уведомлений (только ephemeral). App Clip Card настраивается в App Store Connect, и ошибки в метаданных — частая причина отказа в ревью.
Android Instant Apps строятся на модульной архитектуре: приложение делится на feature-модули, каждый из которых может быть загружен отдельно через Play Feature Delivery. Instant App — это feature-модуль с <dist:module dist:instant="true">. Ограничение — не более 15MB суммарно для instant delivery.
Сравнение показывает, что App Clips выигрывают в сценариях с оплатой благодаря интеграции с Apple Pay — конверсия выше на 20% по сравнению с Instant Apps в аналогичных кейсах. Instant Apps лучше подходят для игровых демо и сервисов, где требуется быстрый доступ к функциям через Google Search.
| Параметр |
App Clips |
Instant Apps |
| Макс. размер |
15 MB |
15 MB |
| Триггеры запуска |
NFC, QR, URL, Safari |
URL, Google Search, Play Store |
| Общий Keychain |
Через App Group |
Через SharedPreferences/Keystore |
| Рекомендуемый сценарий |
Оплата, посадочный, демо |
Игровое демо, разовые сервисы |
Что входит в работу?
-
Аудит текущей архитектуры: определяем, какие точки входа нужны вашему приложению — виджет, Live Activity, App Clip, Instant App.
-
Прототипирование: визуальная модель расширения с учётом гайдлайнов платформы (Apple HIG, Material Design).
-
Разработка: реализация на Swift (iOS) или Kotlin (Android) с использованием WidgetKit, ActivityKit, App Clip API, Play Feature Delivery.
-
Интеграция: настройка App Group, Keychain sharing, push-сертификатов, provisioning profile.
-
Тестирование: на реальных устройствах (iPhone, iPad, Android) и в симуляторах. Для Live Activities — тест через
xcrun simctl push.
-
Публикация: подготовка метаданных для App Store Connect (App Clip Card) и Google Play Console (Instant App configuration).
-
Документация и обучение: описание архитектуры, инструкции по обновлению виджетов, troubleshooting push-уведомлений.
Процесс работы
-
Аналитика: какие функции приложения реально нужны вне него, и какой механизм подходит. Виджет с прогнозом — WidgetKit. Трекинг доставки в реальном времени — Live Activity. Оплата на кассе — App Clip.
-
Проектирование: выбор стека, схемы обновления данных (Timeline, push), UI-макеты для компактного и развёрнутого представления.
-
Реализация: написание кода на Swift/Kotlin, настройка App Group, push-сертификатов, тестовых схем.
-
Тест: каждое расширение тестируется изолированно. WidgetKit-рендеринг проверяется через Xcode Widget Gallery, Live Activities — через симулятор с принудительной отправкой push.
-
Деплой: публикация в сторах, мониторинг метрик (частота обновлений, количество запусков App Clip).
Сроки ориентировочно
| Тип расширения |
Срок (рабочие дни) |
| Простой информационный виджет |
от 5 до 10 |
| Интерактивный виджет (AppIntent) |
от 10 до 15 |
| Live Activity с push |
от 10 до 20 |
| App Clip с оплатой |
от 20 до 30 |
| Instant App (Android) |
от 15 до 25 |
Стоимость рассчитывается индивидуально после аудита. Оценка даётся в течение 2 рабочих дней.
Типичные ошибки при разработке расширений
-
Слишком частое обновление виджета — приводит к троттлингу и пустому состоянию. Рекомендуем интервал не менее 15 минут (см. Apple Human Interface Guidelines в WidgetKit documentation).
-
Игнорирование shared container — виджет не видит данные, потому что использует свой
UserDefaults, а не App Group.
-
Отсутствие fallback для Live Activities — если push не доставлен, пользователь видит устаревшие данные. Нужен механизм периодического опроса через
Activity.update с pushType: nil.
-
Неправильные метаданные App Clip Card — частая причина отклонения в App Store Review. Например, некорректный URL или недостающий значок.
Свяжитесь с нами, чтобы оценить, какое расширение подходит вашему приложению. Закажите аудит текущих точек входа — мы найдём неочевидные сценарии для виджетов и App Clips. Получите консультацию инженера по архитектуре уже сегодня.