Notification Service Extension — как работи обработката на известия

Автор: IT Sectr Публикувано: 2026-06-16 Време за четене: 9 мин

Notification Service Extension е разширение на iOS, което прихваща push известието веднага след получаване, но преди показване на потребителя. Разширението може да дешифрира криптиран payload, да изтегли и прикачи медиен файл, да промени текста или заглавието на известието в реално време. Според Apple Developer Documentation (2025), за активиране на разширението сървърът трябва да изпрати ключа mutable-content:1 в атрибутите на известието — това е единственото условие за стартиране на UNNotificationServiceExtension.

Основни точки

  • Notification Service Extension модифицира push известието преди показването му на потребителя на iOS устройство
  • За активиране на разширението е необходим параметърът mutable-content:1 в payload на известието от сървъра
  • Основният протокол — UNNotificationServiceExtension с методите didReceive(_:withContentHandler:) и serviceExtensionTimeWillExpire()
  • Разширението може да изтегля медийни прикачени файлове от мрежата и да ги прикачва към известието чрез UNNotificationAttachment
  • Времето за изпълнение е ограничено — системата отделя около 30 секунди за пълна обработка на едно известие

Какво е Notification Service Extension

Notification Service Extension е разширение на приложение в iOS, което прихваща входящото push известие от страна на устройството и позволява промяна на съдържанието му, преди потребителят да го види. Това е единственият тип разширение за известия, което работи със съдържание, а не с показване.

Ключовата разлика от Notification Content Extension: Service Extension работи преди показване на известието и може да промени заглавието, тялото, звуковия файл и прикачените файлове. Content Extension работи след показване и управлява само визуалното представяне на готовото известие. Тези две разширения могат да работят заедно: Service Extension изтегля изображение, а Content Extension го показва в персонализиран интерфейс.

Разширението се активира автоматично при получаване на push известие с атрибут mutable-content:1 в aps речника. iOS стартира разширението на фонов режим, предава му оригиналния UNNotificationRequest и очаква модифицирана версия за показване.

Обработка на push известия в движение

UNNotificationServiceExtension получава пълния UNNotificationRequest с оригинално съдържание. Разширението може да модифицира всяко поле на UNNotificationContent: title, subtitle, body, userInfo, attachments и sound. Промените се прилагат преди показване на известието.

Типични сценарии за използване

Дешифриране на съдържание — ако push известието съдържа криптиран payload, разширението го дешифрира преди показване. Изтегляне на медия — прикачване на изображение или видео към известието. Локализация — адаптиране на текста на известието към регионалните настройки на устройството. Обогатяване на данни — добавяне на допълнителна информация от локално хранилище или кеш.

Според Apple, най-честият сценарий сред приложенията е изтегляне на изображения за богати медийни известия. Сървърът изпраща URL на изображението в payload, разширението го изтегля в временна директория и създава UNNotificationAttachment, който системата показва в стандартен или персонализиран интерфейс.

Модификация на текст и заглавие

Разширението може напълно да презапише текста на известието, да замени заглавието или да добави subtitle. Например, приложение за съобщения може да получи криптирано известие, да го дешифрира в разширението и да покаже четим текст. Или новинарско приложение може да добави категория на новината в подзаглавието преди показване.

swift
override func didReceive(
    _ request: UNNotificationRequest,
    withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void
) {
    let content = request.content.mutableCopy()
        as! UNMutableNotificationContent
    if let imageURL = content.userInfo["media-url"]
        as? String {
        downloadAndAttach(imageURL: imageURL,
            content: content,
            handler: contentHandler)
    }
}

Протокол UNNotificationServiceExtension

UNNotificationServiceExtension — базовият клас, от който наследява Service Extension. Класът дефинира два метода на жизнения цикъл: didReceive(_:withContentHandler:) — основният метод за обработка, и serviceExtensionTimeWillExpire() — обработчикът за изтичане на времето.

Метод didReceive:withContentHandler:

didReceive(_:withContentHandler:) се извиква при получаване на известие. Разширението получава UNNotificationRequest и closure contentHandler, който трябва да бъде извикан с модифицираното UNMutableNotificationContent. Разширението е задължено да извика contentHandler — ако не го направи, iOS ще покаже оригиналното известие след изтичане на таймаута.

Важно: разширението може да обработва само едно известие наведнъж. Ако пристигнат няколко известия едновременно, iOS създава отделни инстанции на разширението за всяко. Не може да се използва глобално състояние за последователна обработка.

Метод serviceExtensionTimeWillExpire:

serviceExtensionTimeWillExpire() се извиква от системата, когато оставащото време за изпълнение наближава края си. В този метод трябва незабавно да се извика contentHandler със съдържанието, което е готово в момента — дори ако медийният файл все още не е изтеглен. Ако contentHandler не бъде извикан в този метод, iOS ще покаже оригиналното известие.

Препоръчва се в този метод да се съхранява минимално приемливо съдържание — например известие с текст и заглавие, но без изображение, чието изтегляне не е завършило навреме.

Криптиране и медийни прикачени файлове

UNNotificationAttachment — обект, създаден от разширението за прикачване на медиен файл към известието. Разширението изтегля файла от мрежата, записва го в временна директория и създава UNNotificationAttachment с посочване на типа съдържание.

Създаване на прикачен файл от изтеглен файл

UNNotificationAttachment се създава с помощта на инициализатора init(identifier:url:options:). URL трябва да сочи към локален файл в временната директория, достъпна за разширението. След създаване, прикаченият файл се добавя към масива attachments на UNMutableNotificationContent.

Apple препоръчва използването на URLSession с фонова конфигурация за изтегляне — при използване на стандартен URLSession, изтеглянето блокира нишката и изразходва време от 30-секундния лимит. Фоновият URLSession продължава изтеглянето дори след приключване на разширението, а резултатът може да бъде използван при следващо стартиране.

Дешифриране на криптиран payload

Ако сървърът изпраща криптирано известие, разширението трябва да дешифрира payload преди извикване на contentHandler. Дешифрирането обикновено включва искане на ключ от Keychain или App Group, дешифриране чрез CommonCrypto и замяна на body или userInfo на известието. При грешка при дешифриране трябва да се извика contentHandler с оригиналното съдържание — така че потребителят поне да види, че известието е пристигнало, дори и да е нечетимо.

swift
func downloadAndAttach(
    imageURL: String,
    content: UNMutableNotificationContent,
    handler: @escaping (UNNotificationContent) -> Void
) {
    let task = URLSession.shared.dataTask(with:
        URL(string: imageURL)!) { data, _, _ in
        let url = FileManager.default
            .temporaryDirectory
            .appendingPathComponent("image.jpg")
        try? data?.write(to: url)
        let attachment = try? UNNotificationAttachment(
            identifier: "image", url: url)
        content.attachments = [attachment].compactMap { $0 }
        handler(content)
    }
    task.resume()
}

Таймаути и fallback механизми

Notification Service Extension работи в строги времеви рамки. iOS отделя фиксирано време за изпълнение — около 30 секунди от момента на активиране. Ако разширението не извика contentHandler в това време, системата принудително прекратява процеса и показва оригиналното известие без промени.

Стратегия за graceful degradation

Препоръчва се прилагане на многостепенен fallback: първо опитайте да изтеглите медия, при успех — извикайте contentHandler с пълно съдържание; при неуспех — извикайте contentHandler с текст, но без медия; при критична грешка — предайте оригиналното съдържание. Този подход гарантира, че потребителят винаги ще види известие, а не празен екран.

Според Apple, най-честата причина за таймаути е изтеглянето на големи медийни файлове при бавна връзка. За намаляване на риска се препоръчва оптимизиране на размера на изображенията на сървъра — изпращане на прегледи до 300 KB вместо пълна резолюция. Изображенията с пълна резолюция трябва да се изтеглят при отваряне на приложението.

Мониторинг на производителността

За проследяване на таймаути и грешки на разширението може да се използва os_log за запис на диагностични съобщения в Unified Logging System. Въпреки че директното логване във файл в разширението е затруднено, os_log позволява анализ на производителността чрез Console.app на устройството за разработка. Apple препоръчва добавяне на метрики при всяко извикване на didReceive — време за изтегляне, размер на файла, резултат от операцията.

swift
override func serviceExtensionTimeWillExpire() {
    let fallback = bestEffortContent as?
        UNMutableNotificationContent
        ?? request.content.mutableCopy()
        as! UNMutableNotificationContent
    contentHandler(fallback)
}

Често задавани въпроси

Как сървърът активира Notification Service Extension?

Сървърът добавя ключа mutable-content:1 в aps речника на push известието. Без този параметър системата игнорира разширението и показва стандартното известие.

Може ли разширението да се използва без mutable-content?

Не. mutable-content:1 е задължително условие за активиране на Service Extension. Ако ключът липсва или е зададен на 0, известието се показва без извикване на разширението.

Какво се случва при превишаване на 30-секундния лимит?

iOS принудително прекратява разширението и показва оригиналното известие без промени. За да избегнете това, имплементирайте serviceExtensionTimeWillExpire() с минимално приемливо съдържание.

Как да предадем ключове за криптиране на разширението?

Чрез App Group (споделен UserDefaults или файл) или Keychain със споделен достъп между приложението и разширението. Директното предаване на ключове в payload на известието не е безопасно.

Колко медийни файла могат да бъдат прикачени в Service Extension?

До 4 прикачени файла на известие, всеки до 50 MB. Общият размер на прикачените файлове влияе на времето за изтегляне — колкото повече файлове, толкова по-висок е рискът от таймаут.

Резюме

  • Notification Service Extension модифицира push известията на устройството преди показване, редактирайки текст, заглавие и медийни прикачени файлове
  • За активиране е необходим ключът mutable-content:1 в aps речника — без него разширението не стартира
  • Основният протокол UNNotificationServiceExtension дефинира методите didReceive и serviceExtensionTimeWillExpire за обработка
  • Разширението може да изтегля медия от мрежата, да дешифрира payload и да добавя до 4 прикачени файла към известието
  • Времето за изпълнение е ограничено до около 30 секунди — при превишаване iOS показва оригиналното известие
  • Препоръчва се стратегия за graceful degradation с многостепенен fallback за предотвратяване на празни известия

Ще разработим мобилно приложение под ключ

IT Sectr създава iOS и Android приложения за стартъпи и бизнеси от 2017 г. Ще ви консултираме и ще предложим най-доброто решение.

Обсъдете проекта

Прочетете също