Notification Service Extension — jak działa przetwarzanie powiadomień

Autor: IT Sectr Opublikowano: 2026-06-16 Czas czytania: 9 min

Notification Service Extension to rozszerzenie iOS, które przechwytuje powiadomienie push zaraz po jego otrzymaniu, ale przed wyświetleniem użytkownikowi. Rozszerzenie może odszyfrować zaszyfrowany payload, pobrać i dołączyć plik multimedialny, zmienić tekst lub tytuł powiadomienia w czasie rzeczywistym. Według Apple Developer Documentation (2025), aby aktywować rozszerzenie, serwer musi wysłać klucz mutable-content:1 w atrybutach powiadomienia — jest to jedyny warunek uruchomienia UNNotificationServiceExtension.

Najważniejsze

  • Notification Service Extension modyfikuje powiadomienie push przed jego wyświetleniem użytkownikowi na urządzeniu iOS
  • Do aktywacji rozszerzenia wymagany jest parametr mutable-content:1 w payload powiadomienia od serwera
  • Główny protokół — UNNotificationServiceExtension z metodami didReceive(_:withContentHandler:) i serviceExtensionTimeWillExpire()
  • Rozszerzenie może pobierać załączniki multimedialne z sieci i dołączać je do powiadomienia przez UNNotificationAttachment
  • Czas wykonania jest ograniczony — system przydziela około 30 sekund na pełne przetworzenie jednego powiadomienia

Czym jest Notification Service Extension

Notification Service Extension to app extension w iOS, które przechwytuje przychodzące powiadomienie push po stronie urządzenia i pozwala zmienić jego zawartość, zanim użytkownik je zobaczy. Jest to jedyny typ rozszerzenia powiadomień, który działa z treścią, a nie z wyświetlaniem.

Kluczowa różnica w porównaniu z Notification Content Extension: Service Extension działa przed wyświetleniem powiadomienia i może zmienić tytuł, treść, plik dźwiękowy i załączniki. Content Extension działa po wyświetleniu i zarządza tylko wizualną prezentacją gotowego powiadomienia. Te dwa rozszerzenia mogą działać razem: Service Extension pobiera obraz, a Content Extension wyświetla go w niestandardowym interfejsie.

Rozszerzenie aktywuje się automatycznie po otrzymaniu powiadomienia push z atrybutem mutable-content:1 w słowniku aps. iOS uruchamia rozszerzenie w tle, przekazuje mu oryginalny UNNotificationRequest i oczekuje zmodyfikowanej wersji do wyświetlenia.

Przetwarzanie powiadomień push na bieżąco

UNNotificationServiceExtension otrzymuje pełny UNNotificationRequest z oryginalną zawartością. Rozszerzenie może modyfikować dowolne pola UNNotificationContent: title, subtitle, body, userInfo, attachments i sound. Zmiany są stosowane przed wyświetleniem powiadomienia.

Typowe scenariusze użycia

Odszyfrowanie treści — jeśli powiadomienie push zawiera zaszyfrowany payload, rozszerzenie odszyfrowuje go przed wyświetleniem. Pobieranie multimediów — dołączanie obrazu lub wideo do powiadomienia. Lokalizacja — dostosowanie tekstu powiadomienia do ustawień regionalnych urządzenia. Wzbogacanie danych — dodawanie dodatkowych informacji z lokalnego magazynu lub pamięci podręcznej.

Według Apple, najczęstszym scenariuszem w aplikacjach jest pobieranie obrazów dla bogatych powiadomień multimedialnych. Serwer wysyła URL obrazu w payload, rozszerzenie pobiera go do katalogu tymczasowego i tworzy UNNotificationAttachment, który system wyświetla w standardowym lub niestandardowym interfejsie.

Modyfikacja tekstu i tytułu

Rozszerzenie może całkowicie przepisać text powiadomienia, zastąpić tytuł lub dodać subtitle. Na przykład aplikacja komunikatora może otrzymać zaszyfrowane powiadomienie, odszyfrować je w rozszerzeniu i wyświetlić czytelny tekst. Aplikacja informacyjna może dodać kategorię wiadomości w podtytule przed wyświetleniem.

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)
    }
}

Protokół UNNotificationServiceExtension

UNNotificationServiceExtension — klasa bazowa, od której dziedziczy Service Extension. Klasa definiuje dwie metody cyklu życia: didReceive(_:withContentHandler:) — główna metoda przetwarzania, oraz serviceExtensionTimeWillExpire() — obsługa przekroczenia czasu.

Metoda didReceive:withContentHandler:

didReceive(_:withContentHandler:) jest wywoływana po otrzymaniu powiadomienia. Rozszerzenie otrzymuje UNNotificationRequest i zamknięcie contentHandler, które należy wywołać ze zmodyfikowanym UNMutableNotificationContent. Rozszerzenie musi wywołać contentHandler — jeśli tego nie zrobi, iOS wyświetli oryginalne powiadomienie po przekroczeniu limitu czasu.

Ważne: rozszerzenie może przetwarzać tylko jedno powiadomienie na raz. Jeśli nadejdzie kilka powiadomień jednocześnie, iOS tworzy osobne instancje rozszerzenia dla każdego. Nie można używać stanu globalnego do sekwencyjnego przetwarzania.

Metoda serviceExtensionTimeWillExpire:

serviceExtensionTimeWillExpire() jest wywoływana przez system, gdy pozostały czas wykonania dobiega końca. W tej metodzie należy natychmiast wywołać contentHandler z treścią, która jest gotowa w danym momencie — nawet jeśli plik multimedialny jeszcze się nie pobrał. Jeśli contentHandler nie zostanie wywołany w tej metodzie, iOS wyświetli oryginalne powiadomienie.

Zaleca się zachowanie w tej metodzie minimalnie akceptowalnej treści — na przykład powiadomienia z tekstem i tytułem, ale bez obrazu, którego pobranie nie zakończyło się na czas.

Szyfrowanie i załączniki multimedialne

UNNotificationAttachment — obiekt tworzony przez rozszerzenie w celu dołączenia pliku multimedialnego do powiadomienia. Rozszerzenie pobiera plik z sieci, zapisuje go w katalogu tymczasowym i tworzy UNNotificationAttachment z określeniem typu treści.

Tworzenie załącznika z pobranego pliku

UNNotificationAttachment jest tworzony za pomocą inicjalizatora init(identifier:url:options:). URL musi wskazywać na lokalny plik w katalogu tymczasowym dostępnym dla rozszerzenia. Po utworzeniu załącznik jest dodawany do tablicy attachments w UNMutableNotificationContent.

Apple zaleca używanie URLSession z konfiguracją w tle do pobierania — przy użyciu standardowej URLSession pobieranie blokuje wątek i zużywa czas z 30-sekundowego limitu. URLSession w tle kontynuuje pobieranie nawet po zakończeniu rozszerzenia, a wynik może być użyty przy następnym uruchomieniu.

Odszyfrowanie zaszyfrowanego payload

Jeśli serwer wysyła zaszyfrowane powiadomienie, rozszerzenie musi odszyfrować payload przed wywołaniem contentHandler. Odszyfrowanie zazwyczaj obejmuje pobranie klucza z Keychain lub App Group, deszyfrowanie przez CommonCrypto i zastąpienie body lub userInfo powiadomienia. W przypadku błędu deszyfrowania należy wywołać contentHandler z oryginalną zawartością — aby użytkownik przynajmniej widział, że powiadomienie przyszło, nawet jeśli jest nieczytelne.

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()
}

Przekroczenia czasu i mechanizmy fallback

Notification Service Extension działa w ścisłych ramach czasowych. iOS przydziela stały czas na wykonanie — około 30 sekund od momentu aktywacji. Jeśli rozszerzenie nie wywoła contentHandler w tym czasie, system wymusza zakończenie procesu i wyświetla oryginalne powiadomienie bez zmian.

Strategia graceful degradation

Zaleca się implementację wielopoziomowego fallback: najpierw spróbować pobrać multimedia, w przypadku sukcesu — wywołać contentHandler z pełną treścią; w przypadku niepowodzenia — wywołać contentHandler z tekstem, ale bez multimediów; w przypadku krytycznego błędu — przekazać oryginalną zawartość. Takie podejście gwarantuje, że użytkownik zawsze zobaczy powiadomienie, a nie pusty ekran.

Według Apple, najczęstszą przyczyną przekroczeń czasu jest pobieranie dużych plików multimedialnych przy wolnym połączeniu. Aby zmniejszyć ryzyko, zaleca się optymalizację rozmiaru obrazów na serwerze — wysyłanie podglądów do 300 KB zamiast pełnej rozdzielczości. Obrazy w pełnej rozdzielczości warto pobierać już po otwarciu aplikacji.

Monitorowanie wydajności

Do śledzenia przekroczeń czasu i błędów rozszerzenia można użyć os_log do zapisu komunikatów diagnostycznych w Unified Logging System. Mimo że bezpośrednie logowanie do pliku w rozszerzeniu jest utrudnione, os_log pozwala analizować wydajność przez Console.app na urządzeniu deweloperskim. Apple zaleca dodawanie metryk przy każdym wywołaniu didReceive — czasu pobierania, rozmiaru pliku, wyniku operacji.

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

Często zadawane pytania

Jak serwer aktywuje Notification Service Extension?

Serwer dodaje klucz mutable-content:1 do słownika aps powiadomienia push. Bez tego parametru system ignoruje rozszerzenie i wyświetla standardowe powiadomienie.

Czy można użyć rozszerzenia bez mutable-content?

Nie. mutable-content:1 jest obowiązkowym warunkiem aktywacji Service Extension. Jeśli klucz jest nieobecny lub ustawiony na 0, powiadomienie jest wyświetlane bez wywołania rozszerzenia.

Co się dzieje po przekroczeniu 30-sekundowego limitu?

iOS wymusza zakończenie rozszerzenia i wyświetla oryginalne powiadomienie bez zmian. Aby tego uniknąć, zaimplementuj serviceExtensionTimeWillExpire() z minimalnie akceptowalną treścią.

Jak przekazać klucze szyfrowania do rozszerzenia?

Przez App Group (wspólny UserDefaults lub plik) lub Keychain ze wspólnym dostępem między aplikacją a rozszerzeniem. Bezpośrednie przekazywanie kluczy w payload powiadomienia jest niebezpieczne.

Ile plików multimedialnych można dołączyć w Service Extension?

Do 4 załączników na jedno powiadomienie, każdy do 50 MB. Łączny rozmiar załączników wpływa na czas pobierania — im więcej plików, tym większe ryzyko przekroczenia czasu.

Podsumowanie

  • Notification Service Extension modyfikuje powiadomienia push na urządzeniu przed ich wyświetleniem, zmieniając tekst, tytuł i załączniki multimedialne
  • Do aktywacji wymagany jest klucz mutable-content:1 w słowniku aps — bez niego rozszerzenie nie uruchamia się
  • Główny protokół UNNotificationServiceExtension definiuje metody didReceive i serviceExtensionTimeWillExpire do przetwarzania
  • Rozszerzenie może pobierać multimedia z sieci, odszyfrowywać payload i dodawać do 4 załączników do powiadomienia
  • Czas wykonania jest ograniczony do około 30 sekund — po przekroczeniu iOS wyświetla oryginalne powiadomienie
  • Zaleca się strategię graceful degradation z wielopoziomowym fallback, aby zapobiec pustym powiadomieniom

Opracujemy aplikację mobilną pod klucz

IT Sectr tworzy aplikacje na iOS i Androida dla startupów i firm od 2017 roku. Doradzimy Ci i zaproponujemy najlepsze rozwiązanie.

Omów projekt

Przeczytaj również