Notification Service Extension هو امتداد لنظام iOS يعترض الإشعار الفوري قبل عرضه للمستخدم ويسمح بتعديل المحتوى. يمكن للامتداد فك تشفير البيانات المشفرة، تنزيل المرفقات الوسائطية، تغيير النص، أو إضافة حقول مخصصة. وفقًا لـ Apple Developer, 2025، Notification Service Extension لديه حتى 30 ثانية لإكمال المهمة في الخلفية.
النقاط الرئيسية
Notification Service Extension هو امتداد تطبيق في iOS يعمل قبل عرض الإشعار الفوري. يسمح للخادم بإرسال حمولة صغيرة بينما يقوم الامتداد بإثرائها بالمحتوى: تنزيل الصور، فك تشفير البيانات، استبدال النص. يرى المستخدم الإشعار المُعالَج بالفعل.
عندما يستقبل iOS إشعارًا فوريًا، يتحقق النظام من وجود امتداد للتطبيق. إذا كان الامتداد مسجلاً، يبدأه iOS في عملية خلفية ويمرر محتوى الإشعار عبر طريقة didReceive(_:withContentHandler:). يعالج الامتداد المحتوى ويستدعي contentHandler بالمحتوى المعدل. إذا لم يكتمل الامتداد خلال 30 ثانية، يعرض النظام الإشعار الأصلي.
يكون Service Extension ضروريًا في السيناريوهات التي يتطلب فيها محتوى الإشعار معالجة على الجهاز. الاتصالات الآمنة: يرسل الخادم حمولة مشفرة، يقوم الامتداد بفك تشفيرها محليًا. الإشعارات الوسائطية الغنية: يرسل الخادم رابط صورة، يقوم الامتداد بتنزيلها وإرفاقها. التوطين الديناميكي: يقوم الامتداد باستبدال النص بلغة الجهاز.
| السيناريو | بدون امتداد | مع الامتداد |
|---|---|---|
| صورة | غير مدعومة | يتم تنزيلها وعرضها |
| تشفير | الخادم يحتفظ بالمفتاح | فك التشفير على الجهاز |
| نص | محدد مسبقًا على الخادم | استبدال ديناميكي |
| تحقق | لا يتم التحقق | إلغاء الإشعارات الضارة |
يعمل Notification Service Extension في بيئة محدودة. أقصى وقت للتنفيذ هو 30 ثانية. لا يمكن للامتداد الوصول إلى التخزين الرئيسي للتطبيق (باستثناء App Group). حجم الامتداد محدود بـ 50 ميجابايت. عند تجاوز الوقت، يستدعي النظام contentHandler بالمحتوى الأصلي وتفقد جميع التغييرات.
في Xcode، يتم إضافة Notification Service Extension عن طريق إنشاء target جديد من نوع Notification Service Extension. يقوم Xcode بإنشاء فئة قالب NotificationService التي ترث من UNNotificationServiceExtension، بطريقتين: didReceive و serviceExtensionTimeWillExpire.
في Xcode، اختر File → New → Target → Notification Service Extension. أدخل اسمًا (مثل PushNotificationService) واختر لغة Swift. تأكد من إضافة target إلى التطبيق الرئيسي ومن وجود التوقيع الصحيح. بعد الإنشاء، سيتم إنشاء فئة NotificationService.swift مع تنفيذ أساسي.
يحتوي Info.plist للامتداد على مفتاح NSExtension مع المفاتيح الفرعية NSExtensionPointIdentifier (com.apple.usernotifications.service) و NSExtensionPrincipalClass (اسم وحدة التحكم الخاصة بك). بالإضافة إلى ذلك، يمكن تحديد NSExtensionAttributes مع قواعد تنشيط الامتداد. يقوم Xcode بإنشاء هذه الإعدادات تلقائيًا.
التنفيذ الأساسي يعيد تعريف didReceive، ويعدل محتوى الإشعار، ويستدعي contentHandler. إذا استغرقت المعالجة وقتًا طويلاً، يتم استدعاء serviceExtensionTimeWillExpire، حيث يجب إكمال العمل بالحالة الحالية.
import UserNotifications
class NotificationService: UNNotificationServiceExtension {
var contentHandler: ((UNNotificationContent) -> Void)?
var bestAttemptContent: UNMutableNotificationContent?
override func didReceive(
request: UNNotificationRequest,
withContentHandler handler: @escaping (UNNotificationContent) -> Void
) {
contentHandler = handler
bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent)
if let bestAttemptContent = bestAttemptContent {
bestAttemptContent.title = "[تمت المعالجة] \(bestAttemptContent.title)"
contentHandler?(bestAttemptContent)
}
}
override func serviceExtensionTimeWillExpire() {
if let contentHandler = contentHandler,
let bestAttemptContent = bestAttemptContent {
contentHandler(bestAttemptContent)
}
}
}
أحد الاستخدامات الرئيسية لـ Service Extension هو فك تشفير محتوى الإشعار على الجهاز. يرسل الخادم حمولة مشفرة ويقوم الامتداد بفك تشفيرها باستخدام مفتاح مخزن في Keychain أو App Group. يضمن ذلك عدم إمكانية اعتراض المحتوى أثناء النقل.
يقوم الخادم بتشفير نص الإشعار باستخدام مفتاح متماثل (AES-256). يتم الاتفاق على مفتاح التشفير مسبقًا بين العميل والخادم. يستقبل الامتداد السلسلة المشفرة في حقل data من الحمولة، ويفك تشفيرها، ويستبدلها في حقول الإشعار. مفتاح المستخدم يمكن الحصول عليه من Keychain بعد المصادقة.
override func didReceive(
request: UNNotificationRequest,
withContentHandler handler: @escaping (UNNotificationContent) -> Void
) {
guard let content = request.content.mutableCopy()
as? UNMutableNotificationContent else {
handler(request.content)
return
}
guard let encryptedData = content.userInfo["encrypted_data"]
as? String else {
handler(content)
return
}
let decrypted = CryptoService.decrypt(encryptedData)
content.body = decrypted.body
content.title = decrypted.title
handler(content)
}
لا يجب تخزين مفتاح فك التشفير في كود الامتداد أو NSUserDefaults. استخدم iOS Keychain مع الوصول عبر App Group لكي يتمكن كل من التطبيق والامتداد من قراءة المفتاح. استخدم Security.framework مع خوارزمية AES-256-GCM لتوليد المفاتيح على العميل.
الاستخدام الأكثر شيوعًا لـ Notification Service Extension هو تنزيل الصور وملفات GIF والفيديو لعرضها في الإشعار. يرسل الخادم رابط ملف وسائطي ويقوم الامتداد بتنزيله وحفظه في دليل مؤقت وإنشاء UNNotificationAttachment.
يستقبل الامتداد رابط الصورة من حقل payload في الإشعار. باستخدام URLSession، يقوم الامتداد بتنزيل الملف إلى دليل مؤقت. بعد اكتمال التنزيل، يتم إنشاء UNNotificationAttachment مع الرابط المحلي. يتم تمرير المرفق إلى المحتوى المعدل. iOS تلقائيًا يعرض الصورة في الواجهة القياسية أو في Notification Content Extension.
private func downloadAndAttachMedia(
content: UNMutableNotificationContent,
mediaUrl: String,
handler: @escaping (UNNotificationContent) -> Void
) {
guard let url = URL(string: mediaUrl) else {
handler(content)
return
}
let task = URLSession.shared.downloadTask(with: url) { localUrl, _, error in
guard let localUrl = localUrl, error == nil else {
handler(content)
return
}
let attachment = try? UNNotificationAttachment(
identifier: "media",
url: localUrl,
options: nil
)
if let attachment = attachment {
content.attachments = [attachment]
}
handler(content)
}
task.resume()
}
يدعم iOS الصيغ التالية للعرض في الإشعارات: JPEG، PNG، GIF (ثابتة)، فيديو MPEG-4 حتى 50 ميجابايت. للملفات الصوتية، يتم دعم MP3 و AAC و ALAC. مهم: يجب تنزيل جميع الملفات الوسائطية في غضون 30 ثانية. للملفات الكبيرة، يُوصى بالقص على الخادم أو التحميل التدريجي.
إدارة حد 30 ثانية هي مهمة رئيسية عند تطوير Notification Service Extension. إذا لم يكمل الامتداد المعالجة في الوقت المحدد، يستدعي النظام serviceExtensionTimeWillExpire ويعرض المحتوى الأصلي. يجب توفير سيناريوهات احتياط لكل نوع من أنواع المعالجة.
قم بتقسيم المهام حسب الأولوية. نفذ التعديلات الحرجة (فك التشفير، التوطين الأساسي) أولاً. التحسينات الاختيارية (تنزيل الصور، إثراء النص) تأتي ثانيًا. استخدم URLSession مع مهلة للطلبات الشبكية لتجنب إنفاق الحد بأكمله على عملية واحدة.
إذا فشل تنزيل الصورة أو أعاد فك تشفير الحمولة خطأ، يجب على الامتداد استدعاء contentHandler بالمحتوى الأصلي. لا تنهي الامتداد أبدًا دون استدعاء contentHandler — فهذا يؤدي إلى فقدان الإشعار. الاحتياط الآمن يجب دائمًا تضمينه في كود الامتداد.
override func didReceive(
request: UNNotificationRequest,
withContentHandler handler: @escaping (UNNotificationContent) -> Void
) {
let content = (request.content.mutableCopy()
as? UNMutableNotificationContent) ?? request.content
// مهمة حرجة: فك التشفير
var decryptedContent = tryDecryptPayload(content)
// مهمة اختيارية: الوسائط
guard let mediaUrl = decryptedContent.userInfo["media_url"]
as? String else {
handler(decryptedContent)
return
}
downloadAndAttachMedia(
content: decryptedContent,
mediaUrl: mediaUrl,
handler: handler
)
}
لاختبار Notification Service Extension، استخدم Xcode: حدد target الامتداد، شغله على المحاكي، وأرسل إشعارًا فوريًا عبر الطرفية أو Firebase Console. سجل كل مرحلة من مراحل المعالجة باستخدام os_log — يساعد ذلك في تشخيص مشكلات التوقيت والتنزيل.
الأسئلة الشائعة
يستدعي النظام serviceExtensionTimeWillExpire، ثم يعرض الإشعار الأصلي دون تغييرات. يتم تجاهل جميع الملفات التي تم تنزيلها والتعديلات.
نعم، إذا استدعيت contentHandler بمحتوى فارغ (UNNotificationContent بحقول فارغة)، لن يتم عرض الإشعار. يُستخدم هذا لتصفية إشعارات السبام أو البيانات غير الصحيحة.
يمكن تمرير الرمز في userInfo من payload الإشعار أو الحصول عليه من Keychain عبر App Group. لا يُوصى بتخزين الرموز في UserDefaults للامتداد.
يجب توقيع الامتداد بنفس شهادة المطور المستخدمة للتطبيق الرئيسي. للإنتاج، يلزم شهادة إنتاج مع تفعيل إمكانية Push Notifications.
قم بتوصيل الجهاز بـ Xcode، حدد target الامتداد في خطة التشغيل، وأرسل إشعارًا فوريًا عبر Firebase Console. نقاط التوقف في الامتداد تعمل بنفس الطريقة كما في التطبيق الرئيسي.
الملخص
سنقوم بتطوير تطبيق جوال جاهز
تقدم IT Sectr تطبيقات iOS وAndroid للشركات الناشئة والشركات منذ عام 2017. سوف نقدم لك النصح ونقترح أفضل حل.
اقرأ أيضًا