Вы получили задачу: кастомный интерфейс для push-уведомления iOS с картой доставки и кнопками «Принять» / «Отклонить». Стандартный UI iOS не подходит — нужно своё расширение. Notification Content Extension — единственный способ добавить интерактивный предпросмотр без открытия приложения. Часто стандартного preview недостаточно: нужно отобразить карту, форму заказа или кастомную кнопку. Для этого iOS предоставляет механизм Notification Content Extension. Однако его настройка требует аккуратной работы с UNNotificationCategory, правильной конфигурации Info.plist и понимания sandbox-ограничений. За годы работы мы накопили 12+ успешных кейсов — от логистических карт до интерактивных опросов.
Как работает Notification Content Extension для iOS?
Content Extension — это отдельный таргет с собственным UIViewController, реализующим UNNotificationContentExtension. Когда пользователь разворачивает уведомление с соответствующей категорией, система загружает ваш контроллер и вызывает didReceive(_:). Кнопки действий добавляются через UNNotificationCategory в основном приложении. Payload обязан содержать category с тем же идентификатором.
class NotificationViewController: UIViewController, UNNotificationContentExtension { @IBOutlet weak var titleLabel: UILabel! @IBOutlet weak var bodyLabel: UILabel! func didReceive(_ notification: UNNotification) { let content = notification.request.content titleLabel.text = content.title bodyLabel.text = content.body // парсим content.userInfo для дополнительных данных } func didReceive(_ response: UNNotificationResponse, completionHandler completion: @escaping (UNNotificationContentExtensionResponseOption) -> Void) { // обработка нажатия на action buttons completion(.dismissAndForwardAction) } } Ключевой нюанс: регистрация категорий — реализация notification content
Категорию нужно зарегистрировать до отправки первого уведомления — обычно в AppDelegate или UNUserNotificationCenter.current().setNotificationCategories([...]). Идентификатор категории должен совпадать с UNNotificationExtensionCategory в Info.plist расширения.
Как настроить кастомный размер UI?
Высота задаётся в Info.plist через UNNotificationExtensionInitialContentSizeRatio (отношение высоты к ширине). Например, 0.6 для карточки заказа. Если нужна динамическая высота, меняем preferredContentSize в коде. Мы используем этот приём, чтобы подстраиваться под разный контент — от короткого сообщения до карты с маршрутом.
| Тип контента | InitialContentSizeRatio | preferredContentSize (по коду) |
|---|---|---|
| Текст с одной кнопкой | 0.2 | 150x320 |
| Карта с маршрутом | 0.8 | 400x320 |
| Форма ввода | 0.5 | 300x320 |
Медиа-вложения доступны через notification.request.content.attachments. Если Notification Service Extension предварительно скачал изображение, Content Extension отобразит его в кастомном UIImageView без системного превью.
Почему нельзя использовать сетевые запросы?
Это не баг, а осознанное ограничение sandbox. Данные должны приходить в payload (до 4KB для APNs) или через attachment. Если нужен live-счёт из матча, обновляйте UI через UNUserNotificationCenter.current().getDeliveredNotifications() — мы так делали для спортивного приложения, и это сработало.
Интерактивные элементы (UIButton, UITextField) поддерживаются, но тапы обрабатываются через didReceive(_:completionHandler:), а не через IBAction. Эта деталь сломала первый же UIKit-проект новичка. В SwiftUI легче: используем onTapGesture с передачей действия через замыкание.
Сравнение подходов: UIKit vs SwiftUI
| Характеристика | UIKit | SwiftUI |
|---|---|---|
| Объём кода | ~150 строк | ~50 строк |
| Сложность анимаций | Средняя | Низкая (withAnimation) |
| Поддержка iOS | 10+ | 16+ |
| Интерактивность | Через delegation | Через связывание |
| Скорость разработки | Медленнее в 2 раза | Быстрее (меньше шаблонного кода) |
SwiftUI-решение занимает в 3 раза меньше строк и проще в поддержке, но требует iOS 16+.
Как обновлять данные без сети?
Используйте App Groups для общего хранилища. Notification Service Extension может сохранить актуальные данные в shared container, а Content Extension — прочитать их перед отображением. Альтернатива — передавать небольшой флаг в payload и подгружать статический контент из бандла.
Пример payload для карты доставки
{ "aps": { "alert": { "title": "Заказ #123", "body": "Курьер выехал" }, "category": "delivery_map" }, "latitude": 53.9, "longitude": 27.56, "order_id": "123" } Что входит в работу «под ключ»
- Создание таргета Notification Content Extension
- Кастомный UI (XIB, UIKit или SwiftUI) с адаптивной высотой
- Регистрация
UNNotificationCategoryс action buttons в основном приложении - Обработка action responses и передача управления приложению
- Настройка App Groups для доступа к shared данным
- Тестирование на симуляторе и реальном устройстве через TestFlight
Процесс работы
- Аналитика — определяем типы уведомлений, payload-структуру, категории. Оцениваем целевые iOS-версии.
- Проектирование — UI/UX прототип с учётом ограничений (без сети, 4KB). Выбираем UIKit или SwiftUI.
- Реализация — пишем код Extension + интеграция с основным приложением. Настраиваем provisioning profiles.
- Тестирование — проверка на разных устройствах и iOS-версиях, включая симуляцию push-уведомлений.
- Деплой — подготовка App Store Connect, публикация через TestFlight, финальное ревью.
Сроки и гарантия
Базовый кастомный UI для одного типа уведомлений: от 1 до 2 дней. С несколькими категориями, интерактивными элементами и интеграцией с Service Extension: от 2 до 3 дней. Гарантируем, что решение пройдёт ревью App Store (Section 4.2). Наши инженеры имеют опыт 5+ лет в iOS. Бюджет на разработку базового расширения — от 500 до 1000 у.е., а внедрение позволяет сэкономить до 30% времени на адаптацию пользователей.
Типичные ошибки при реализации
- Забыть указать
UNNotificationExtensionCategoryв Info.plist — расширение не сработает. - Использовать прямое сетевое соединение — падение в рантайме.
- Пытаться изменить размер через constraints без учёта
preferredContentSize— получите обрезанный UI. - Не синхронизировать идентификаторы категорий между основным приложением и Extension.
Подробнее о возможностях Content Extension в официальной документации Apple.
Оценим ваш проект бесплатно — свяжитесь с нами. Закажите интеграцию под ключ, и мы реализуем кастомный UI для любых push-уведомлений с учётом всех ограничений iOS.







