Notification Extension to mechanizm iOS, który umożliwia modyfikację treści i wyglądu powiadomień push przed ich wyświetleniem użytkownikowi. Rozszerzenia działają po stronie systemu operacyjnego w oddzielnym procesie: UNNotificationServiceExtension przetwarza przychodzącą treść, a UNNotificationContentExtension zarządza interfejsem. Według Apple Developer Documentation, 2026, Service Extension ma do 30 sekund na wykonanie zadań przed wyświetleniem powiadomienia. To ograniczenie jest krytyczne przy pobieraniu załączników lub deszyfrowaniu danych.
Najważniejsze
Notification Extension to komponent programowy iOS, który rozszerza standardowe zachowanie powiadomień push, dodając możliwość modyfikacji treści i personalizacji interfejsu. W przeciwieństwie do zwykłych powiadomień, które są wyświetlane przez system w standardowej formie, rozszerzenia pozwalają programiście wpływać na treść przed wyświetleniem i tworzyć unikalny interfejs użytkownika.
Apple udostępnia dwa typy Notification Extension do różnych celów: UNNotificationServiceExtension odpowiada za przetwarzanie przychodzącego payloadu, a UNNotificationContentExtension zarządza wyświetlaniem. Service Extension uruchamia się przed wyświetleniem powiadomienia i ma ograniczony czas na wykonanie — do 30 sekund według Apple Developer Documentation. Content Extension aktywuje się po interakcji użytkownika z powiadomieniem i wyświetla niestandardowy widok.
Standardowe powiadomienie push iOS jest wyświetlane przez system automatycznie na podstawie pól alert, title i subtitle z JSON-payloadu. Notification Extension przechwytuje sterowanie: Service Extension otrzymuje surowy payload, modyfikuje go i przekazuje systemowi do wyświetlenia. Content Extension zastępuje standardowy baner dowolnym interfejsem z dowolnymi elementami sterowania.
Gdy urządzenie otrzyma push z kluczem mutable-content: 1, system uruchamia Service Extension w oddzielnym procesie. Proces rozszerzenia jest izolowany od głównej aplikacji i ma własną piaskownicę z limitem pamięci 50 MB. Po zakończeniu przetwarzania rozszerzenie wywołuje completion handler, przekazując zmodyfikowany UNNotificationContent systemowi do wyświetlenia.
UNNotificationServiceExtension to podstawowe narzędzie do programowej zmiany powiadomień push przed ich wyświetleniem użytkownikowi. Rozszerzenie aktywuje się automatycznie po otrzymaniu powiadomienia, w którego payloadzie ustawiono flagę mutable-content: 1. W ciągu 30 sekund rozszerzenie może pobrać załącznik multimedialny, zmienić tekst, odszyfrować zaszyfrowane dane lub wzbogacić treść.
Rozszerzenie implementuje dwie kluczowe metody z protokołu UNNotificationServiceExtension. Metoda didReceive otrzymuje przychodzące żądanie z surowym UNNotificationRequest i umożliwia jego modyfikację przez completion handler z nowym UNNotificationContent. Metoda serviceExtensionTimeWillExpire jest wywoływana przez system na sekundę przed upływem limitu czasu — w niej należy zakończyć przetwarzanie i przekazać bieżący (ewentualnie częściowy) wynik.
Rozważmy scenariusz, w którym serwer wysyła push z URL-em obrazu w niestandardowym polu. Service Extension pobiera ten obraz przez sieć, tworzy UNNotificationAttachment i dodaje go do treści. UNNotificationAttachment przyjmuje lokalny plik obrazu, wideo lub audio i automatycznie kopiuje go do sandboxa rozszerzenia. Po utworzeniu attachment rozszerzenie przekazuje zaktualizowaną treść systemowi.
class NotificationService: UNNotificationServiceExtension {
override func didReceive(_ request: UNNotificationRequest,
withContentHandler contentHandler:
@escaping (UNNotificationContent) -> Void) {
let userInfo = request.content.userInfo
guard let imageURL = URL(string: userInfo["image-url"] as! String)
else { contentHandler(request.content); return }
let attachment = try! UNNotificationAttachment(
identifier: "image", url: imageURL,
options: [UNNotificationAttachmentOptionsTypeHintKey: "jpg"])
let modifiedContent = request.content.mutableCopy()
as! UNMutableNotificationContent
modifiedContent.attachments = [attachment]
contentHandler(modifiedContent)
}
override func serviceExtensionTimeWillExpire() {
contentHandler?(bestAttemptContent ?? request.content)
}
}
Przy częstym wysyłaniu powiadomień z tymi samymi załącznikami zaleca się buforowanie pobranych plików na urządzeniu. FileManager udostępnia dostęp do katalogu pamięci podręcznej rozszerzenia, który jest zachowywany między uruchomieniami. Skraca to czas przetwarzania kolejnych powiadomień i zmniejsza obciążenie sieci. Według Apple buforowanie załączników może skrócić czas przetwarzania do 2–5 sekund zamiast pełnego pobierania.
UNNotificationContentExtension pozwala zastąpić standardowy baner powiadomienia dowolnym interfejsem utworzonym w Interface Builder lub SwiftUI. Rozszerzenie aktywuje się, gdy użytkownik wykona akcję z powiadomieniem: dotknięcie, przesunięcie w dół lub 3D Touch. Content Extension otrzymuje treść już przetworzoną przez Service Extension i wyświetla ją w niestandardowym widoku.
Każdy Content Extension jest powiązany z jedną lub kilkoma kategoriami powiadomień przez Info.plist. Kategoria jest określana na serwerze polem category w payloadzie APNS. System automatycznie wybiera odpowiednie rozszerzenie na podstawie kategorii otrzymanego powiadomienia. Interfejs buduje się przez storyboard z użyciem standardowych komponentów UIKit lub SwiftUI View.
Content Extension obsługuje niestandardowe przyciski i procedury obsługi dotknięć zdefiniowane w UNNotificationAction. UNNotificationAction jest tworzony na etapie rejestracji kategorii i może być wprowadzaniem tekstu przez UNTextInputNotificationAction. Gdy użytkownik naciśnie przycisk, rozszerzenie otrzymuje callback didReceive z identyfikatorem działania i może wykonać odpowiednią logikę — otworzyć URL, wysłać żądanie do serwera lub zaktualizować interfejs.
Content Extension działa w izolowanym procesie z własną pętlą wykonawczą i limitem pamięci około 50 MB. Wydajność rozszerzenia jest krytyczna, ponieważ systemowy watchdog kończy proces po przekroczeniu limitów. Zaleca się unikanie ciężkich obliczeń, pobierania dużych obrazów i długotrwałych żądań sieciowych wewnątrz Content Extension.
UNNotificationAttachment to obiekt, który dodaje plik multimedialny do powiadomienia push: obraz, wideo, audio lub GIF. Załącznik jest tworzony z lokalnego URL pliku, który musi znajdować się w piaskownicy rozszerzenia. Maksymalny rozmiar załącznika nie może przekraczać 10 MB, w przeciwnym razie system odrzuci attachment podczas tworzenia.
Apple obsługuje ograniczony zestaw formatów załączników multimedialnych. Obrazy — JPEG, PNG, GIF (w tym animowane), TIFF. Wideo — MPEG, MP4, MOV z maksymalnym czasem trwania 30 sekund. Audio — MP3, AAC, WAV, CAF. Dla każdego formatu można określić typ przez UNNotificationAttachmentOptionsTypeHintKey, co pomaga systemowi poprawnie przetworzyć plik.
Ponieważ payload push zawiera tylko URL, a nie sam plik, pobieranie załącznika musi odbywać się wewnątrz Service Extension. Maksymalny czas pobierania jest ograniczony do 30 sekund, dlatego zaleca się używanie URLSession z minimalnymi ustawieniami i wyłączanie pobierania przy słabym sygnale. Jeśli załącznik nie został pobrany na czas, powiadomienie jest wyświetlane bez multimediów — to domyślne zachowanie systemu.
Rozważmy pełny przykład Notification Extension, który pobiera obraz, ściąga go i dodaje do powiadomienia. NotificationService dziedziczy po UNNotificationServiceExtension i nadpisuje metodę didReceive. W przykładzie pokazano obsługę opcjonalnych pól, tworzenie attachment i wywołanie completion handlera ze zmodyfikowaną treścią.
import UserNotifications
class NotificationService: UNNotificationServiceExtension {
var contentHandler: ((UNNotificationContent) -> Void)?
var bestAttemptContent: UNMutableNotificationContent?
override func didReceive(
_ request: UNNotificationRequest,
withContentHandler contentHandler:
@escaping (UNNotificationContent) -> Void
) {
self.contentHandler = contentHandler
self.bestAttemptContent =
(request.content.mutableCopy()
as! UNMutableNotificationContent)
guard let attachmentURLString =
bestAttemptContent?.userInfo["attachment-url"] as? String,
let url = URL(string: attachmentURLString)
else {
contentHandler(request.content)
return
}
URLSession.shared.downloadTask(with: url) {
[weak self] localURL, _, error in
guard let localURL = localURL, error == nil
else {
contentHandler(request.content)
return
}
let attachment = try! UNNotificationAttachment(
identifier: "media", url: localURL)
self?.bestAttemptContent?.attachments = [attachment]
contentHandler(self?.bestAttemptContent
?? request.content)
}.resume()
}
override func serviceExtensionTimeWillExpire() {
if let content = bestAttemptContent {
contentHandler?(content)
}
}
}
Do poprawnego działania rozszerzenia należy zarejestrować kategorie powiadomień w Info.plist. Klucz NSExtensionPointIdentifier ustawia się na com.apple.usernotifications.service dla Service Extension lub com.apple.usernotifications.content dla Content Extension. Kategorie są określane w AppDelegate podczas uruchamiania aplikacji przez UNUserNotificationCenter, a rozszerzenie aktywuje się tylko dla powiadomień z odpowiednią kategorią w payloadzie.
Często zadawane pytania
Service Extension modyfikuje treść przed wyświetleniem powiadomienia — dodaje multimedia, zmienia tekst, deszyfruje dane. Content Extension zastępuje interfejs powiadomienia niestandardowym po interakcji użytkownika. Service Extension działa przed wyświetleniem, Content Extension — po.
System przydziela 30 sekund na wykonanie kodu w didReceive. Jeśli przetwarzanie nie zakończy się w tym czasie, wywoływana jest metoda serviceExtensionTimeWillExpire, w której należy przekazać bieżący wynik. Zaleca się zmieścić w 10–15 sekund, uwzględniając pobieranie załączników.
Tak, SwiftUI jest obsługiwane w Content Extension od iOS 16. View owija się w UIHostingController i dodaje do storyboard. Jednak ze względu na limity pamięci zaleca się używanie SwiftUI tylko dla prostych interfejsów z minimalną liczbą elementów.
W przypadku błędu pobierania lub przekroczenia limitu czasu wystarczy wywołać completion handler z oryginalną treścią bez attachment. System wyświetli powiadomienie w standardowej formie bez multimediów. Rejestruj błędy przez OSLog do diagnostyki, ale nie blokuj wyświetlania powiadomienia.
Rozszerzenie działa w izolowanym procesie z limitem około 50 MB. Po przekroczeniu limitu system zabija proces przez watchdog. Unikaj pobierania dużych plików, przechowywania obrazów w pamięci i wycieków podczas pracy z URLSession.
Podsumowanie
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.
Przeczytaj również