Notification Extension este un mecanism iOS care permite modificarea conținutului și aspectului notificărilor push înainte de afișarea lor utilizatorului. Extensiile funcționează în sistemul de operare într-un proces separat: UNNotificationServiceExtension procesează conținutul primit, iar UNNotificationContentExtension gestionează interfața. Conform Apple Developer Documentation, 2026, Service Extension are până la 30 de secunde pentru a executa sarcinile înainte de afișarea notificării. Această limitare este critică la încărcarea atașamentelor sau la decriptarea datelor.
Principalele puncte
Notification Extension este o componentă software iOS care extinde comportamentul standard al notificărilor push, adăugând posibilitatea de modificare a conținutului și personalizare a interfeței. Spre deosebire de notificările obișnuite care sunt afișate de sistem în formă standard, extensiile permit dezvoltatorului să influențeze conținutul înainte de afișare și să creeze o interfață unică pentru utilizator.
Apple oferă două tipuri de Notification Extension pentru scopuri diferite: UNNotificationServiceExtension se ocupă de procesarea payload-ului primit, iar UNNotificationContentExtension gestionează afișarea. Service Extension se lansează înainte de afișarea notificării și are timp limitat pentru execuție — până la 30 de secunde conform Apple Developer Documentation. Content Extension se activează după ce utilizatorul interacționează cu notificarea și afișează o vizualizare personalizată.
Notificarea push standard iOS este afișată automat de sistem pe baza câmpurilor alert, title și subtitle din JSON-payload. Notification Extension preia controlul: Service Extension primește payload-ul brut, îl modifică și îl transmite sistemului pentru afișare. Content Extension înlocuiește banner-ul standard cu o interfață arbitrară cu orice elemente de control.
Când dispozitivul primește o notificare push cu cheia mutable-content: 1, sistemul lansează Service Extension într-un proces separat. Procesul extensiei este izolat de aplicația principală și are propriul sandbox cu o limită de memorie de 50 MB. După finalizarea procesării, extensia apelează completion handler-ul, transmițând UNNotificationContent modificat sistemului pentru afișare.
UNNotificationServiceExtension este instrumentul principal pentru modificarea programatică a notificărilor push înainte de afișarea lor utilizatorului. Extensia se activează automat la primirea unei notificări în al cărei payload este setat flag-ul mutable-content: 1. În termen de 30 de secunde, extensia poate încărca un atașament media, poate modifica textul, poate decripta datele criptate sau poate îmbogăți conținutul.
Extensia implementează două metode cheie din protocolul UNNotificationServiceExtension. Metoda didReceive primește cererea primită cu UNNotificationRequest brut și permite modificarea acesteia prin completion handler cu un nou UNNotificationContent. Metoda serviceExtensionTimeWillExpire este apelată de sistem cu o secundă înainte de expirarea timeout-ului — în ea trebuie să finalizați procesarea și să transmiteți rezultatul curent (posibil parțial).
Să analizăm un scenariu în care serverul trimite un push cu URL-ul unei imagini într-un câmp personalizat. Service Extension încarcă această imagine prin rețea, creează UNNotificationAttachment și îl adaugă la conținut. UNNotificationAttachment primește un fișier local de imagine, video sau audio și îl copiază automat în sandbox-ul extensiei. După crearea atașamentului, extensia transmite conținutul actualizat sistemului.
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)
}
}
La trimiterea frecventă a notificărilor cu aceleași atașamente, se recomandă stocarea în cache a fișierelor încărcate pe dispozitiv. FileManager oferă acces la directorul de cache al extensiei, care se păstrează între lansări. Aceasta reduce timpul de procesare a notificărilor ulterioare și scade încărcarea rețelei. Conform Apple, stocarea în cache a atașamentelor poate reduce timpul de procesare la 2–5 secunde în loc de încărcarea completă.
UNNotificationContentExtension permite înlocuirea banner-ului standard al notificării cu o interfață personalizată creată în Interface Builder sau SwiftUI. Extensia se activează când utilizatorul efectuează o acțiune cu notificarea: atingere, glisare în jos sau 3D Touch. Content Extension primește conținutul deja procesat de Service Extension și îl afișează într-o vizualizare personalizată.
Fiecare Content Extension este legat de una sau mai multe categorii de notificări prin Info.plist. Categoria este determinată pe server de câmpul category din payload-ul APNS. Sistemul selectează automat extensia potrivită pe baza categoriei notificării primite. Interfața se construiește prin storyboard folosind componente standard UIKit sau SwiftUI View.
Content Extension suportă butoane personalizate și gestionarea atingerilor definite în UNNotificationAction. UNNotificationAction se creează în etapa de înregistrare a categoriei și poate fi de tip introducere text prin UNTextInputNotificationAction. Când utilizatorul apasă un buton, extensia primește callback-ul didReceive cu identificatorul acțiunii și poate executa logica corespunzătoare — deschide un URL, trimite o cerere la server sau actualizează interfața.
Content Extension funcționează într-un proces izolat cu propria buclă de execuție și o limită de memorie de aproximativ 50 MB. Performanța extensiei este critică, deoarece watchdog-ul sistemului termină procesul la depășirea limitelor. Se recomandă evitarea calculelor grele, încărcării imaginilor mari și cererilor de rețea lungi în interiorul Content Extension.
UNNotificationAttachment este un obiect care adaugă un fișier media la notificarea push: imagine, video, audio sau GIF. Atașamentul se creează dintr-un URL local al fișierului care trebuie să se afle în sandbox-ul extensiei. Dimensiunea maximă a atașamentului nu trebuie să depășească 10 MB, altfel sistemul va respinge atașamentul la creare.
Apple suportă un set limitat de formate pentru atașamentele media. Imagini — JPEG, PNG, GIF (inclusiv animate), TIFF. Video — MPEG, MP4, MOV cu durata maximă de 30 de secunde. Audio — MP3, AAC, WAV, CAF. Pentru fiecare format se poate specifica tipul prin UNNotificationAttachmentOptionsTypeHintKey, ceea ce ajută sistemul să proceseze corect fișierul.
Deoarece payload-ul push conține doar URL-ul, nu și fișierul propriu-zis, încărcarea atașamentului trebuie efectuată în interiorul Service Extension. Timpul maxim de încărcare este limitat la 30 de secunde, de aceea se recomandă utilizarea URLSession cu setări minime și dezactivarea încărcării la semnal slab. Dacă atașamentul nu s-a încărcat la timp, notificarea se afișează fără media — acesta este comportamentul implicit al sistemului.
Să analizăm un exemplu complet de Notification Extension care încarcă o imagine, o descarcă și o adaugă la notificare. NotificationService moștenește UNNotificationServiceExtension și suprascrie metoda didReceive. În exemplu este prezentată procesarea câmpurilor opționale, crearea atașamentului și apelarea completion handler-ului cu conținutul modificat.
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)
}
}
}
Pentru funcționarea corectă a extensiei, trebuie înregistrate categoriile de notificări în Info.plist. Cheia NSExtensionPointIdentifier se setează la com.apple.usernotifications.service pentru Service Extension sau com.apple.usernotifications.content pentru Content Extension. Categoriile se definesc în AppDelegate la lansarea aplicației prin UNUserNotificationCenter, iar extensia se activează doar pentru notificările cu categoria corespunzătoare în payload.
Întrebări frecvente
Service Extension modifică conținutul înainte de afișarea notificării — adaugă media, schimbă textul, decriptează datele. Content Extension înlocuiește interfața notificării cu una personalizată după interacțiunea utilizatorului. Service Extension funcționează înainte de afișare, Content Extension — după.
Sistemul alocă 30 de secunde pentru executarea codului în didReceive. Dacă procesarea nu se finalizează în acest timp, se apelează serviceExtensionTimeWillExpire, unde trebuie transmis rezultatul curent. Se recomandă încadrarea în 10–15 secunde, ținând cont de încărcarea atașamentelor.
Da, SwiftUI este suportat în Content Extension începând cu iOS 16. View-ul se înfășoară în UIHostingController și se adaugă pe storyboard. Totuși, din cauza limitelor de memorie, se recomandă utilizarea SwiftUI doar pentru interfețe simple cu un număr minim de elemente.
La eroare de încărcare sau depășire a limitei de timp, apelați completion handler-ul cu conținutul original fără atașament. Sistemul va afișa notificarea în formă standard fără media. Înregistrați erorile prin OSLog pentru diagnosticare, dar nu blocați afișarea notificării.
Extensia funcționează într-un proces izolat cu o limită de aproximativ 50 MB. La depășirea limitei, sistemul ucide procesul prin watchdog. Evitați încărcarea fișierelor mari, stocarea imaginilor în memorie și scurgerile de memorie la lucrul cu URLSession.
Rezumat
Vom dezvolta o aplicație mobilă la cheie
IT Sectr creează aplicații iOS și Android pentru startup-uri și afaceri din 2017. Vă vom consilia și vă vom propune cea mai bună soluție.
Citiți și