Notification Extension: المفاهيم الأساسية وأنواع الامتدادات والإعداد

المؤلف: IT Sectr نُشر: 2026-03-20 وقت القراءة: 8 دق

Notification Extension هي آلية في iOS تتيح تعديل محتوى ومظهر الإشعارات الفورية قبل عرضها للمستخدم. تعمل الامتدادات على جانب نظام التشغيل في عملية منفصلة: UNNotificationServiceExtension يعالج المحتوى الوارد، بينما UNNotificationContentExtension يدير الواجهة. وفقًا لـ Apple Developer Documentation, 2026، يحصل Service Extension على ما يصل إلى 30 ثانية لتنفيذ المهام قبل عرض الإشعار. هذا القيد بالغ الأهمية عند تنزيل المرفقات أو فك تشفير البيانات.

الملخص

  • Service Extension — يعترض الإشعار قبل العرض، ويتيح تعديل النص وإضافة الوسائط وفك تشفير البيانات بحد أقصى 30 ثانية.
  • Content Extension — ينشئ واجهة إشعار مخصصة مع واجهة مستخدم مخصصة وأزرار ومعالجة النقرات عبر storyboard أو SwiftUI.
  • مرفقات الوسائط — يتم إضافة الصور والفيديو والصوت عبر UNNotificationAttachment في Service Extension قبل تمريرها إلى Content Extension.
  • التسجيل — يتم تسجيل كلا الامتدادين في Info.plist كـ targets منفصلة مع تحديد فئات الإشعارات و NSExtensionPointIdentifier.
  • القيود — لا تملك الامتدادات إمكانية الوصول إلى التطبيق الرئيسي، وتعمل في بيئة معزولة بحد ذاكرة 50 ميجابايت.

ما هو Notification Extension

Notification Extension هو مكون برمجي في iOS يوسع السلوك القياسي للإشعارات الفورية بإضافة إمكانية تعديل المحتوى وتخصيص الواجهة. على عكس الإشعارات العادية التي يعرضها النظام بتنسيق قياسي، تتيح الامتدادات للمطور التأثير على المحتوى قبل العرض وإنشاء واجهة مستخدم فريدة.

نوعان من امتدادات الإشعارات

توفر Apple نوعين من Notification Extension لأغراض مختلفة: UNNotificationServiceExtension يتولى معالجة الحمولة الواردة، بينما UNNotificationContentExtension يدير العرض. يتم تشغيل Service Extension قبل عرض الإشعار وله وقت تنفيذ محدود — يصل إلى 30 ثانية وفقًا لـ Apple Developer Documentation. يتم تنشيط Content Extension بعد تفاعل المستخدم مع الإشعار ويعرض عرضًا مخصصًا.

الفرق عن الإشعارات القياسية

يتم عرض الإشعار الفوري القياسي في iOS تلقائيًا بواسطة النظام بناءً على حقول alert و title و subtitle من حمولة JSON. Notification Extension يعترض التحكم: Service Extension يتلقى الحمولة الخام ويعدلها ويمررها إلى النظام للعرض. Content Extension يستبدل البانر القياسي بواجهة مخصصة مع أي عناصر تحكم.

دورة حياة الامتداد

عندما يستلم الجهاز إشعارًا فوريًا بمفتاح mutable-content: 1، يقوم النظام بتشغيل Service Extension في عملية منفصلة. عملية الامتداد معزولة عن التطبيق الرئيسي ولها بيئة خاصة بها بحد ذاكرة 50 ميجابايت. بعد اكتمال المعالجة، يستدعي الامتداد completion handler، ويمرر UNNotificationContent المعدل إلى النظام للعرض.

UNNotificationServiceExtension: تعديل المحتوى

UNNotificationServiceExtension هو الأداة الرئيسية لتعديل الإشعارات الفورية برمجيًا قبل عرضها للمستخدم. يتم تنشيط الامتداد تلقائيًا عند استلام إشعار به علم mutable-content: 1 في حمولته. في غضون 30 ثانية، يمكن للامتداد تنزيل مرفق وسائط، تغيير النص، فك تشفير البيانات المشفرة أو إثراء المحتوى.

طرق بروتوكول UNNotificationServiceExtension

يقوم الامتداد بتنفيذ طريقتين رئيسيتين من بروتوكول UNNotificationServiceExtension. طريقة didReceive تستلم الطلب الوارد مع UNNotificationRequest الخام وتتيح التعديل عبر completion handler مع UNNotificationContent جديد. يتم استدعاء طريقة serviceExtensionTimeWillExpire بواسطة النظام قبل ثانية من انتهاء المهلة — فيها يجب إكمال المعالجة وتمرير النتيجة الحالية (ربما الجزئية).

مثال: إضافة صورة إلى الإشعار

لنفترض سيناريو حيث يرسل الخادم إشعارًا مع رابط صورة في حقل مخصص. يقوم Service Extension بتنزيل هذه الصورة عبر الشبكة، وينشئ UNNotificationAttachment ويضيفه إلى المحتوى. UNNotificationAttachment يقبل ملف صورة أو فيديو أو صوت محليًا وينسخه تلقائيًا إلى بيئة الامتداد. بعد إنشاء المرفق، يمرر الامتداد المحتوى المحدث إلى النظام.

swift
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: واجهة مخصصة

UNNotificationContentExtension يتيح استبدال البانر القياسي للإشعار بواجهة مخصصة تم إنشاؤها في Interface Builder أو SwiftUI. يتم تنشيط الامتداد عندما يقوم المستخدم بإجراء على الإشعار: النقر، التمرير لأسفل أو 3D Touch. يتلقى Content Extension المحتوى الذي تمت معالجته بالفعل بواسطة Service Extension ويعرضه في عرض مخصص.

Storyboard وفئات الإشعارات

كل Content Extension يرتبط بفئة إشعار واحدة أو أكثر عبر Info.plist. الفئة يتم تعريفها على الخادم بواسطة حقل category في حمولة APNS. يختار النظام تلقائيًا الامتداد المناسب بناءً على فئة الإشعار المستلم. يتم بناء الواجهة عبر storyboard باستخدام مكونات UIKit القياسية أو SwiftUI View.

معالجة إجراءات المستخدم

يدعم Content Extension أزرارًا مخصصة ومعالجات نقر معرفة في UNNotificationAction. UNNotificationAction يتم إنشاؤه في مرحلة تسجيل الفئة ويمكن أن يدعم إدخال النص عبر UNTextInputNotificationAction. عندما يضغط المستخدم على زر، يتلقى الامتداد استدعاء didReceive مع معرف الإجراء ويمكنه تنفيذ المنطق المقابل — فتح رابط، إرسال طلب إلى الخادم أو تحديث الواجهة.

قيود الأداء

يعمل Content Extension في عملية معزولة مع دورة تشغيل خاصة به وحد ذاكرة حوالي 50 ميجابايت. أداء الامتداد بالغ الأهمية لأن watchdog في النظام ينهي العملية عند تجاوز الحدود. يُوصى بتجنب الحسابات الثقيلة وتحميل الصور الكبيرة والطلبات الشبكية الطويلة داخل Content Extension.

مرفقات الوسائط و UNNotificationAttachment

UNNotificationAttachment هو كائن يضيف ملف وسائط إلى إشعار فوري: صورة، فيديو، صوت أو GIF. يتم إنشاء المرفق من رابط ملف محلي يجب أن يكون في بيئة الامتداد. يجب ألا يتجاوز الحد الأقصى لحجم المرفق 10 ميجابايت، وإلا سيرفض النظام المرفق عند إنشائه.

التنسيقات المدعومة

تدعم Apple مجموعة محدودة من التنسيقات لمرفقات الوسائط. الصور — JPEG، PNG، GIF (بما في ذلك المتحركة)، TIFF. الفيديو — MPEG، MP4، MOV بأقصى مدة 30 ثانية. الصوت — MP3، AAC، WAV، CAF. لكل تنسيق يمكن تحديد النوع عبر UNNotificationAttachmentOptionsTypeHintKey، مما يساعد النظام على معالجة الملف بشكل صحيح.

تنزيل المرفق من الشبكة

نظرًا لأن حمولة الإشعار تحتوي فقط على رابط وليس الملف نفسه، يجب تنفيذ تنزيل المرفق داخل Service Extension. الحد الأقصى لوقت التنزيل هو 30 ثانية، لذلك يُوصى باستخدام URLSession بأقل الإعدادات وتعطيل التنزيل عند ضعف الإشارة. إذا لم يتم تحميل المرفق في الوقت المحدد، يتم عرض الإشعار بدون وسائط — هذا هو السلوك الافتراضي للنظام.

مثال تنفيذ في Swift

لنستعرض مثالاً كاملاً لـ Notification Extension يقوم بتنزيل صورة وحفظها وإضافتها إلى الإشعار. NotificationService يرث من UNNotificationServiceExtension ويعيد تعريف طريقة didReceive. يوضح المثال معالجة الحقول الاختيارية وإنشاء المرفق واستدعاء completion handler بالمحتوى المعدل.

swift
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 للامتداد

لكي يعمل الامتداد بشكل صحيح، يجب تسجيل فئات الإشعارات في Info.plist. مفتاح NSExtensionPointIdentifier يتم تعيينه إلى com.apple.usernotifications.service لـ Service Extension أو com.apple.usernotifications.content لـ Content Extension. يتم تعريف الفئات في AppDelegate عند تشغيل التطبيق عبر UNUserNotificationCenter، ويتم تنشيط الامتداد فقط للإشعارات ذات الفئة المطابقة في الحمولة.

الأسئلة الشائعة

ما الفرق بين Service Extension و Content Extension؟

Service Extension يعدل المحتوى قبل عرض الإشعار — يضيف وسائط ويغير النص ويفك تشفير البيانات. Content Extension يستبدل واجهة الإشعار بواجهة مخصصة بعد تفاعل المستخدم. Service Extension يعمل قبل العرض، Content Extension يعمل بعد العرض.

كم من الوقت مسموح به للمعالجة في Service Extension؟

يخصص النظام 30 ثانية لتنفيذ الكود في didReceive. إذا لم يكتمل المعالجة خلال هذا الوقت، يتم استدعاء serviceExtensionTimeWillExpire حيث يجب تمرير النتيجة الحالية. يُوصى بالبقاء ضمن 10–15 ثانية مع مراعاة تنزيل المرفقات.

هل يمكن استخدام SwiftUI في Content Extension؟

نعم، SwiftUI مدعوم في Content Extension بدءًا من iOS 16. يتم تغليف العرض في UIHostingController وإضافته إلى storyboard. ومع ذلك، نظرًا لحدود الذاكرة، يُوصى باستخدام SwiftUI فقط للواجهات البسيطة بأقل عدد من العناصر.

كيف يتم معالجة أخطاء تنزيل المرفقات؟

في حالة خطأ التنزيل أو تجاوز الوقت، ما عليك سوى استدعاء completion handler بالمحتوى الأصلي بدون مرفق. سيعرض النظام الإشعار بالشكل القياسي بدون وسائط. سجل الأخطاء عبر OSLog للتشخيص، لكن لا تمنع عرض الإشعار.

ما هي حدود الذاكرة لـ Notification Extension؟

يعمل الامتداد في عملية معزولة بحد ذاكرة حوالي 50 ميجابايت. عند تجاوزه، ينهي النظام العملية عبر watchdog. تجنب تحميل الملفات الكبيرة وتخزين الصور في الذاكرة والتسريبات عند العمل مع URLSession.

الخلاصة

  • Notification Extension — آلية في iOS لتعديل الإشعارات الفورية، تتضمن Service Extension (المحتوى) و Content Extension (الواجهة).
  • Service Extension يعالج الحمولة قبل عرض الإشعار بحد 30 ثانية، يمكنه إضافة مرفقات وسائط وفك تشفير البيانات.
  • Content Extension يستبدل البانر القياسي بواجهة مخصصة عبر UIKit أو SwiftUI مع دعم الأزرار التفاعلية.
  • UNNotificationAttachment يضيف الصور والفيديو والصوت إلى الإشعارات، ويدعم تنسيقات مثل JPEG و PNG و MP4 و MP3 وغيرها.
  • تسجيل الامتدادات يتم عبر Info.plist مع تحديد NSExtensionPointIdentifier وفئات الإشعارات للتنشيط.
  • القيود — حد ذاكرة 50 ميجابايت، بيئة معزولة بدون وصول إلى التطبيق الرئيسي، وقت تنفيذ محدود.
  • Notification Extension أداة رئيسية لإنشاء إشعارات مستخدم غنية، تزيد من التفاعل ووظائف اتصالات الدفع في iOS.

سنقوم بتطوير تطبيق جوال جاهز

تقدم IT Sectr تطبيقات iOS وAndroid للشركات الناشئة والشركات منذ عام 2017. سوف نقدم لك النصح ونقترح أفضل حل.

مناقشة المشروع

اقرأ أيضًا