Το Notification Extension είναι ένας μηχανισμός iOS που επιτρέπει την τροποποίηση του περιεχομένου και της εμφάνισης των push ειδοποιήσεων πριν από την εμφάνισή τους στον χρήστη. Οι επεκτάσεις λειτουργούν από την πλευρά του λειτουργικού συστήματος σε ξεχωριστή διεργασία: Το UNNotificationServiceExtension επεξεργάζεται το εισερχόμενο περιεχόμενο, ενώ το UNNotificationContentExtension διαχειρίζεται τη διεπαφή. Σύμφωνα με το Apple Developer Documentation, 2026, το Service Extension έχει έως 30 δευτερόλεπτα για να εκτελέσει εργασίες πριν από την εμφάνιση της ειδοποίησης. Αυτός ο περιορισμός είναι κρίσιμος κατά τη φόρτωση συνημμένων ή την αποκρυπτογράφηση δεδομένων.
Κύρια σημεία
Notification Extension είναι ένα λογισμικό component του iOS που επεκτείνει την τυπική συμπεριφορά των push ειδοποιήσεων, προσθέτοντας δυνατότητα τροποποίησης περιεχομένου και προσαρμογής διεπαφής. Σε αντίθεση με τις συνηθισμένες ειδοποιήσεις που εμφανίζονται από το σύστημα σε τυπική μορφή, οι επεκτάσεις επιτρέπουν στον προγραμματιστή να επηρεάσει το περιεχόμενο πριν από την εμφάνιση και να δημιουργήσει μια μοναδική διεπαφή χρήστη.
Η Apple παρέχει δύο τύπους Notification Extension για διαφορετικούς σκοπούς: UNNotificationServiceExtension είναι υπεύθυνο για την επεξεργασία του εισερχόμενου payload, και το UNNotificationContentExtension διαχειρίζεται την εμφάνιση. Το Service Extension ξεκινά πριν από την εμφάνιση της ειδοποίησης και έχει περιορισμένο χρόνο εκτέλεσης — έως 30 δευτερόλεπτα σύμφωνα με το Apple Developer Documentation. Το Content Extension ενεργοποιείται αφού ο χρήστης αλληλεπιδράσει με την ειδοποίηση και εμφανίζει μια προσαρμοσμένη προβολή.
Η τυπική push ειδοποίηση iOS εμφανίζεται αυτόματα από το σύστημα με βάση τα πεδία alert, title και subtitle από το JSON-payload. Notification Extension παίρνει τον έλεγχο: Το Service Extension λαμβάνει το raw payload, το τροποποιεί και το μεταφέρει στο σύστημα για εμφάνιση. Το Content Extension αντικαθιστά το τυπικό banner με μια αυθαίρετη διεπαφή με οποιαδήποτε στοιχεία ελέγχου.
Όταν η συσκευή λαμβάνει μια push ειδοποίηση με το κλειδί mutable-content: 1, το σύστημα εκκινεί το Service Extension σε ξεχωριστή διεργασία. Η διεργασία επέκτασης είναι απομονωμένη από την κύρια εφαρμογή και έχει το δικό της sandbox με όριο μνήμης 50 MB. Μετά την ολοκλήρωση της επεξεργασίας, η επέκταση καλεί το completion handler, μεταφέροντας το τροποποιημένο UNNotificationContent στο σύστημα για εμφάνιση.
UNNotificationServiceExtension είναι το κύριο εργαλείο για προγραμματική τροποποίηση των push ειδοποιήσεων πριν από την εμφάνισή τους στον χρήστη. Η επέκταση ενεργοποιείται αυτόματα κατά τη λήψη μιας ειδοποίησης της οποίας το payload έχει θέσει τη σημαία mutable-content: 1. Εντός 30 δευτερολέπτων, η επέκταση μπορεί να φορτώσει ένα συνημμένο πολυμέσων, να αλλάξει το κείμενο, να αποκρυπτογραφήσει κρυπτογραφημένα δεδομένα ή να εμπλουτίσει το περιεχόμενο.
Η επέκταση υλοποιεί δύο βασικές μεθόδους από το πρωτόκολλο UNNotificationServiceExtension. Η μέθοδος didReceive λαμβάνει το εισερχόμενο αίτημα με raw UNNotificationRequest και επιτρέπει την τροποποίησή του μέσω completion handler με νέο UNNotificationContent. Η μέθοδος serviceExtensionTimeWillExpire καλείται από το σύστημα ένα δευτερόλεπτο πριν από τη λήξη του χρονικού ορίου — σε αυτήν πρέπει να ολοκληρωθεί η επεξεργασία και να μεταφερθεί το τρέχον (πιθανώς μερικό) αποτέλεσμα.
Εξετάστε ένα σενάριο όπου ο διακομιστής στέλνει push με URL εικόνας σε προσαρμοσμένο πεδίο. Το Service Extension φορτώνει αυτήν την εικόνα μέσω δικτύου, δημιουργεί UNNotificationAttachment και το προσθέτει στο περιεχόμενο. UNNotificationAttachment δέχεται ένα τοπικό αρχείο εικόνας, βίντεο ή ήχου και το αντιγράφει αυτόματα στο sandbox της επέκτασης. Μετά τη δημιουργία του συνημμένου, η επέκταση μεταφέρει το ενημερωμένο περιεχόμενο στο σύστημα.
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)
}
}
Σε συχνή αποστολή ειδοποιήσεων με τα ίδια συνημμένα, συνιστάται η προσωρινή αποθήκευση των ληφθέντων αρχείων στη συσκευή. FileManager παρέχει πρόσβαση στον κατάλογο προσωρινής αποθήκευσης της επέκτασης, ο οποίος διατηρείται μεταξύ εκκινήσεων. Αυτό μειώνει τον χρόνο επεξεργασίας των επόμενων ειδοποιήσεων και το φορτίο δικτύου. Σύμφωνα με την Apple, η προσωρινή αποθήκευση συνημμένων μπορεί να μειώσει τον χρόνο επεξεργασίας σε 2–5 δευτερόλεπτα αντί για πλήρη φόρτωση.
UNNotificationContentExtension επιτρέπει την αντικατάσταση του τυπικού banner ειδοποίησης με μια προσαρμοσμένη διεπαφή που δημιουργείται στο Interface Builder ή SwiftUI. Η επέκταση ενεργοποιείται όταν ο χρήστης εκτελεί μια ενέργεια με την ειδοποίηση: άγγιγμα, σύρσιμο προς τα κάτω ή 3D Touch. Το Content Extension λαμβάνει το περιεχόμενο που έχει ήδη υποστεί επεξεργασία από το Service Extension και το εμφανίζει σε προσαρμοσμένη προβολή.
Κάθε Content Extension συνδέεται με μία ή περισσότερες κατηγορίες ειδοποιήσεων μέσω Info.plist. Η κατηγορία καθορίζεται στον διακομιστή από το πεδίο category στο payload APNS. Το σύστημα επιλέγει αυτόματα τη σωστή επέκταση βάσει της κατηγορίας της ληφθείσας ειδοποίησης. Η διεπαφή δημιουργείται μέσω storyboard χρησιμοποιώντας τυπικά στοιχεία UIKit ή SwiftUI View.
Το Content Extension υποστηρίζει προσαρμοσμένα κουμπιά και χειρισμό αφής που ορίζονται στο UNNotificationAction. UNNotificationAction δημιουργείται στο στάδιο εγγραφής της κατηγορίας και μπορεί να είναι εισαγωγή κειμένου μέσω UNTextInputNotificationAction. Όταν ο χρήστης πατά ένα κουμπί, η επέκταση λαμβάνει το callback didReceive με το αναγνωριστικό ενέργειας και μπορεί να εκτελέσει την αντίστοιχη λογική — άνοιγμα URL, αποστολή αιτήματος στον διακομιστή ή ενημέρωση διεπαφής.
Το Content Extension λειτουργεί σε απομονωμένη διεργασία με τον δικό του κύκλο εκτέλεσης και όριο μνήμης περίπου 50 MB. Η απόδοση της επέκτασης είναι κρίσιμη, καθώς το watchdog του συστήματος τερματίζει τη διεργασία όταν ξεπεραστούν τα όρια. Συνιστάται η αποφυγή βαριών υπολογισμών, φόρτωσης μεγάλων εικόνων και μεγάλων αιτημάτων δικτύου εντός του Content Extension.
UNNotificationAttachment είναι ένα αντικείμενο που προσθέτει ένα αρχείο πολυμέσων στην push ειδοποίηση: εικόνα, βίντεο, ήχο ή GIF. Το συνημμένο δημιουργείται από ένα τοπικό URL αρχείου που πρέπει να βρίσκεται στο sandbox της επέκτασης. Το μέγιστο μέγεθος συνημμένου δεν πρέπει να υπερβαίνει τα 10 MB, διαφορετικά το σύστημα θα απορρίψει το συνημμένο κατά τη δημιουργία.
Η Apple υποστηρίζει περιορισμένο σύνολο μορφών για συνημμένα πολυμέσων. Εικόνες — JPEG, PNG, GIF (συμπεριλαμβανομένων κινούμενων), TIFF. Βίντεο — MPEG, MP4, MOV με μέγιστη διάρκεια 30 δευτερολέπτων. Ήχος — MP3, AAC, WAV, CAF. Για κάθε μορφή μπορεί να καθοριστεί ο τύπος μέσω UNNotificationAttachmentOptionsTypeHintKey, που βοηθά το σύστημα να επεξεργαστεί σωστά το αρχείο.
Δεδομένου ότι το push payload περιέχει μόνο το URL και όχι το ίδιο το αρχείο, η φόρτωση του συνημμένου πρέπει να γίνει εντός του Service Extension. Ο μέγιστος χρόνος φόρτωσης περιορίζεται σε 30 δευτερόλεπτα, επομένως συνιστάται η χρήση URLSession με ελάχιστες ρυθμίσεις και απενεργοποίηση φόρτωσης σε ασθενές σήμα. Εάν το συνημμένο δεν φορτωθεί εγκαίρως, η ειδοποίηση εμφανίζεται χωρίς πολυμέσα — αυτή είναι η προεπιλεγμένη συμπεριφορά του συστήματος.
Ας εξετάσουμε ένα πλήρες παράδειγμα Notification Extension που φορτώνει μια εικόνα, την κατεβάζει και την προσθέτει στην ειδοποίηση. NotificationService κληρονομεί από το UNNotificationServiceExtension και παρακάμπτει τη μέθοδο didReceive. Στο παράδειγμα παρουσιάζεται η επεξεργασία προαιρετικών πεδίων, δημιουργία συνημμένου και κλήση completion handler με τροποποιημένο περιεχόμενο.
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)
}
}
}
Για τη σωστή λειτουργία της επέκτασης, πρέπει να καταχωρηθούν οι κατηγορίες ειδοποιήσεων στο Info.plist. Το κλειδί NSExtensionPointIdentifier ορίζεται σε com.apple.usernotifications.service για Service Extension ή com.apple.usernotifications.content για Content Extension. Οι κατηγορίες ορίζονται στο AppDelegate κατά την εκκίνηση της εφαρμογής μέσω UNUserNotificationCenter, και η επέκταση ενεργοποιείται μόνο για ειδοποιήσεις με την αντίστοιχη κατηγορία στο payload.
Συχνές Ερωτήσεις
Service Extension τροποποιεί το περιεχόμενο πριν από την εμφάνιση της ειδοποίησης — προσθέτει πολυμέσα, αλλάζει κείμενο, αποκρυπτογραφεί δεδομένα. Το Content Extension αντικαθιστά τη διεπαφή ειδοποίησης με προσαρμοσμένη μετά την αλληλεπίδραση του χρήστη. Το Service Extension λειτουργεί πριν από την εμφάνιση, το Content Extension — μετά.
Το σύστημα διαθέτει 30 δευτερόλεπτα για εκτέλεση κώδικα στο didReceive. Εάν η επεξεργασία δεν ολοκληρωθεί σε αυτό το διάστημα, καλείται το serviceExtensionTimeWillExpire, όπου πρέπει να μεταφερθεί το τρέχον αποτέλεσμα. Συνιστάται να ολοκληρώνεται εντός 10–15 δευτερολέπτων, λαμβάνοντας υπόψη τη φόρτωση συνημμένων.
Ναι, το SwiftUI υποστηρίζεται στο Content Extension από το iOS 16. Το View τυλίγεται σε UIHostingController και προστίθεται στο storyboard. Ωστόσο, λόγω περιορισμών μνήμης, συνιστάται η χρήση SwiftUI μόνο για απλές διεπαφές με ελάχιστο αριθμό στοιχείων.
Σε σφάλμα φόρτωσης ή υπέρβαση χρονικού ορίου, απλώς καλέστε το completion handler με το αρχικό περιεχόμενο χωρίς συνημμένο. Το σύστημα θα εμφανίσει την ειδοποίηση σε τυπική μορφή χωρίς πολυμέσα. Καταγράψτε τα σφάλματα μέσω OSLog για διάγνωση, αλλά μην μπλοκάρετε την εμφάνιση της ειδοποίησης.
Η επέκταση λειτουργεί σε απομονωμένη διεργασία με όριο περίπου 50 MB. Κατά την υπέρβαση του ορίου, το σύστημα τερματίζει τη διεργασία μέσω watchdog. Αποφύγετε τη φόρτωση μεγάλων αρχείων, την αποθήκευση εικόνων στη μνήμη και διαρροές μνήμης κατά την εργασία με URLSession.
Σύνοψη
Θα αναπτύξουμε μια εφαρμογή για κινητά έτοιμη για χρήση
Η IT Sectr δημιουργεί εφαρμογές iOS και Android για νεοφυείς επιχειρήσεις και επιχειρήσεις από το 2017. Θα σας συμβουλεύσουμε και θα προτείνουμε την καλύτερη λύση.
Διαβάστε επίσης