Notification Extension مکانیزمی در iOS است که امکان تغییر محتوا و ظاهر اعلانهای push را قبل از نمایش به کاربر فراهم میکند. افزونهها در سمت سیستمعامل در یک فرآیند جداگانه کار میکنند: UNNotificationServiceExtension محتوای دریافتی را پردازش میکند و UNNotificationContentExtension رابط کاربری را مدیریت میکند. بر اساس Apple Developer Documentation, 2026، Service Extension تا ۳۰ ثانیه برای انجام وظایف قبل از نمایش اعلان فرصت دارد. این محدودیت هنگام بارگیری پیوستها یا رمزگشایی دادهها حیاتی است.
نکات کلیدی
Notification Extension یک مؤلفه نرمافزاری iOS است که رفتار استاندارد اعلانهای push را گسترش میدهد و امکان تغییر محتوا و شخصیسازی رابط کاربری را اضافه میکند. برخلاف اعلانهای معمولی که توسط سیستم به شکل استاندارد نمایش داده میشوند، افزونهها به توسعهدهنده اجازه میدهند قبل از نمایش بر محتوا تأثیر بگذارد و یک رابط کاربری منحصربهفرد ایجاد کند.
Apple دو نوع Notification Extension برای اهداف مختلف ارائه میدهد: UNNotificationServiceExtension مسئول پردازش payload دریافتی است و UNNotificationContentExtension نمایش را مدیریت میکند. Service Extension قبل از نمایش اعلان راهاندازی میشود و طبق Apple Developer Documentation زمان محدودی برای اجرا دارد — تا ۳۰ ثانیه. Content Extension پس از تعامل کاربر با اعلان فعال میشود و یک نمای سفارشی نمایش میدهد.
اعلان push استاندارد iOS به صورت خودکار توسط سیستم بر اساس فیلدهای alert، title و subtitle از JSON-payload نمایش داده میشود. Notification Extension کنترل را دریافت میکند: Service Extension payload خام را دریافت میکند، آن را تغییر میدهد و برای نمایش به سیستم تحویل میدهد. Content Extension بنر استاندارد را با یک رابط دلخواه با هر عنصر کنترلی جایگزین میکند.
وقتی دستگاه یک اعلان push با کلید mutable-content: 1 دریافت میکند، سیستم Service Extension را در یک فرآیند جداگانه راهاندازی میکند. فرآیند افزونه از برنامه اصلی ایزوله است و سندباکس خود را با محدودیت حافظه ۵۰ مگابایت دارد. پس از اتمام پردازش، افزونه completion handler را فراخوانی میکند و UNNotificationContent تغییر یافته را برای نمایش به سیستم تحویل میدهد.
UNNotificationServiceExtension ابزار اصلی برای تغییر برنامهریزی شده اعلانهای push قبل از نمایش به کاربر است. افزونه به طور خودکار هنگام دریافت اعلانی که در payload آن پرچم mutable-content: 1 تنظیم شده فعال میشود. در عرض ۳۰ ثانیه افزونه میتواند یک پیوست رسانهای بارگیری کند، متن را تغییر دهد، دادههای رمزگذاری شده را رمزگشایی کند یا محتوا را غنیتر کند.
افزونه دو متد کلیدی از پروتکل UNNotificationServiceExtension را پیادهسازی میکند. متد didReceive درخواست دریافتی با UNNotificationRequest خام را دریافت میکند و امکان تغییر آن را از طریق completion handler با UNNotificationContent جدید فراهم میکند. متد serviceExtensionTimeWillExpire یک ثانیه قبل از اتمام مهلت زمانی توسط سیستم فراخوانی میشود — در این متد باید پردازش را تمام کرده و نتیجه فعلی (احتمالاً جزئی) را تحویل دهید.
سناریویی را در نظر بگیرید که سرور یک push با URL تصویر در یک فیلد سفارشی ارسال میکند. Service Extension این تصویر را از طریق شبکه بارگیری میکند، UNNotificationAttachment میسازد و آن را به محتوا اضافه میکند. UNNotificationAttachment یک فایل محلی تصویر، ویدئو یا صدا را دریافت میکند و به طور خودکار آن را به سندباکس افزونه کپی میکند. پس از ایجاد attachment، افزونه محتوای بهروز شده را به سیستم تحویل میدهد.
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، ذخیرهسازی پیوستها میتواند زمان پردازش را به ۲–۵ ثانیه به جای بارگیری کامل کاهش دهد.
UNNotificationContentExtension امکان جایگزینی بنر استاندارد اعلان با یک رابط سفارشی ایجاد شده در 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 با شناسه action دریافت میکند و میتواند منطق مربوطه را اجرا کند — باز کردن URL، ارسال درخواست به سرور یا بهروزرسانی رابط.
Content Extension در یک فرآیند ایزوله با چرخه اجرای خود و محدودیت حافظه حدود ۵۰ مگابایت کار میکند. عملکرد افزونه حیاتی است زیرا watchdog سیستم در صورت تجاوز از محدودیتها، فرآیند را خاتمه میدهد. توصیه میشود از محاسبات سنگین، بارگیری تصاویر بزرگ و درخواستهای شبکه طولانی در داخل Content Extension خودداری کنید.
UNNotificationAttachment شیئی است که یک فایل رسانهای به اعلان push اضافه میکند: تصویر، ویدئو، صدا یا GIF. پیوست از URL محلی فایل ایجاد میشود که باید در سندباکس افزونه قرار داشته باشد. حداکثر اندازه پیوست نباید از ۱۰ مگابایت تجاوز کند، در غیر این صورت سیستم هنگام ایجاد attachment آن را رد میکند.
Apple مجموعه محدودی از فرمتها را برای پیوستهای رسانهای پشتیبانی میکند. تصاویر — JPEG، PNG، GIF (شامل متحرک)، TIFF. ویدئو — MPEG، MP4، MOV با حداکثر مدت ۳۰ ثانیه. صدا — MP3، AAC، WAV، CAF. برای هر فرمت میتوان نوع را از طریق UNNotificationAttachmentOptionsTypeHintKey مشخص کرد که به سیستم در پردازش صحیح فایل کمک میکند.
از آنجایی که payload push فقط URL را شامل میشود نه خود فایل، بارگیری پیوست باید در داخل Service Extension انجام شود. حداکثر زمان بارگیری به ۳۰ ثانیه محدود شده است، بنابراین توصیه میشود از URLSession با تنظیمات حداقلی استفاده کنید و در سیگنال ضعیف بارگیری را غیرفعال کنید. اگر پیوست به موقع بارگیری نشود، اعلان بدون رسانه نمایش داده میشود — این رفتار پیشفرض سیستم است.
یک مثال کامل از Notification Extension را بررسی میکنیم که تصویری را بارگیری میکند، آن را دانلود میکند و به اعلان اضافه میکند. NotificationService از UNNotificationServiceExtension ارثبری میکند و متد didReceive را بازنویسی میکند. در مثال پردازش فیلدهای اختیاری، ایجاد attachment و فراخوانی 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 برای Service Extension به com.apple.usernotifications.service و برای Content Extension به com.apple.usernotifications.content تنظیم میشود. دستهبندیها در AppDelegate هنگام راهاندازی برنامه از طریق UNUserNotificationCenter تعریف میشوند و افزونه فقط برای اعلانهایی با دستهبندی مربوطه در payload فعال میشود.
سؤالات متداول
Service Extension محتوا را قبل از نمایش اعلان تغییر میدهد — رسانه اضافه میکند، متن را تغییر میدهد، دادهها را رمزگشایی میکند. Content Extension پس از تعامل کاربر، رابط اعلان را با یک رابط سفارشی جایگزین میکند. Service Extension قبل از نمایش کار میکند، Content Extension — بعد از آن.
سیستم ۳۰ ثانیه برای اجرای کد در didReceive اختصاص میدهد. اگر پردازش در این مدت کامل نشود، serviceExtensionTimeWillExpire فراخوانی میشود که در آن باید نتیجه فعلی را تحویل دهید. توصیه میشود با در نظر گرفتن بارگیری پیوستها در ۱۰–۱۵ ثانیه کار را تمام کنید.
بله، SwiftUI از iOS 16 به بعد در Content Extension پشتیبانی میشود. View در UIHostingController قرار میگیرد و به storyboard اضافه میشود. با این حال، به دلیل محدودیت حافظه، توصیه میشود SwiftUI فقط برای رابطهای ساده با حداقل تعداد عناصر استفاده شود.
در صورت خطای بارگیری یا تجاوز از محدودیت زمانی، کافی است completion handler را با محتوای اصلی بدون attachment فراخوانی کنید. سیستم اعلان را به شکل استاندارد بدون رسانه نمایش میدهد. خطاها را برای تشخیص از طریق OSLog ثبت کنید، اما نمایش اعلان را مسدود نکنید.
افزونه در یک فرآیند ایزوله با محدودیت حدود ۵۰ مگابایت کار میکند. در صورت تجاوز از حد، سیستم فرآیند را از طریق watchdog خاتمه میدهد. از بارگیری فایلهای بزرگ، ذخیره تصاویر در حافظه و نشت حافظه هنگام کار با URLSession خودداری کنید.
خلاصه
ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد
IT Sectr از سال 2017 برنامههای iOS و Android را برای استارتاپها و کسبوکارها ایجاد میکند. ما به شما مشاوره میدهیم و بهترین راهحل را پیشنهاد خواهیم کرد.
همچنین بخوانید