Notification Payload هي بنية JSON يرسلها الخادم عبر APNS إلى جهاز iOS، وتحدد محتوى إشعار push والسلوك عند استلامه. تشمل الحمولة مفاتيح إلزامية واختيارية تتحكم في النص، الصوت، الشارة، المرفقات الوسائطية والمعالجة في الخلفية. وفقاً لـ Apple Developer Documentation, 2026، يبلغ الحد الأقصى لحجم الحمولة 4096 بايت للإشعارات العادية و 5120 بايت لدفع VoIP، مما يفرض قيوداً صارمة على كمية البيانات المنقولة.
النقاط الرئيسية
Notification Payload هو كائن JSON يرسله الخادم إلى APNS (خدمة إشعارات Apple الدفع) لتوصيله إلى جهاز iOS. يحتوي الحمولة على جميع البيانات التي يحتاجها النظام لعرض الإشعار: العنوان، النص، الصوت، الشارة والبيانات الوصفية للمعالجة في الخلفية. بنية الحمولة منظمة بصرامة من قبل Apple وتشمل مفاتيح إلزامية للمعالجة الصحيحة من قبل النظام.
عندما يرسل الخادم إشعار push عبر API HTTP/2 لأجهزة APNS، يحتوي الطلب على ترويسات المصادقة وهيكل JSON — الحمولة. يتحقق APNS من صلاحية الحمولة: إذا كان JSON غير صالح أو تجاوز حد الحجم، يعيد خادم Apple خطأ 400 Bad Request. بعد التحقق، يوصل APNS الحمولة إلى الجهاز، حيث يقوم iOS بتحليلها وتحديد كيفية معالجة الإشعار — عرض لافتة، تشغيل مهمة خلفية أو تشغيل صوت.
تطور تنسيق حمولة APNS من حمولة نصية بسيطة في iOS 2 إلى هيكل JSON متعدد المكونات في الإصدارات الحديثة. iOS 10 أضاف دعم المرفقات الوسائطية عبر mutable-content، و iOS 12 أضاف تجميع الإشعارات عبر thread-id، و iOS 15 أدخل supports-live-activities للأنشطة المباشرة. اليوم، يمكن أن تحتوي الحمولة على ما يصل إلى 15 مفتاحاً مختلفاً حسب السلوك المطلوب للإشعار.
الكائن الأصلي للحمولة يحتوي على قاموس aps وحقول مخصصة اختيارية في المستوى العلوي. قاموس aps هو العنصر الإلزامي الوحيد، ولكن داخله يمكن أن تظهر مختلف تركيبات المفاتيح حسب نوع الإشعار: alert، badge، sound، content-available، mutable-content، interruption-level وغيرها.
| مفتاح aps | النوع | الغرض |
|---|---|---|
| alert | String أو Dictionary | نص الإشعار أو كائن بالعنوان والنص الفرعي والنص والتوطين |
| badge | Number | الرقم على أيقونة التطبيق؛ 0 يزيل الشارة |
| sound | String | اسم ملف الصوت أو default لصوت النظام |
| content-available | Number (1) | علامة التنشيط في الخلفية؛ 1 = إشعار صامت |
| mutable-content | Number (1) | علامة تنشيط Service Extension لتعديل المحتوى |
| category | String | معرف الفئة للأزرار و Content Extension |
| thread-id | String | معرف المجموعة لتجميع الإشعارات |
| interruption-level | String | مستوى انقطاع الإشعار: passive، active، time-sensitive، critical |
| relevance-score | Number (0–1) | أولوية الإشعار لنظام الترتيب الذكي |
يمكن أن يكون مفتاح alert سلسلة بسيطة (تصبح نص الإشعار) أو قاموساً بحقول title، subtitle و body. تنسيق القاموس يسمح بتعيين العنوان والعنوان الفرعي بشكل منفصل عن النص الرئيسي. للإشعارات المحلية، تستخدم المفاتيح title-loc-key، title-loc-args، loc-key و loc-args التي تشير إلى Localizable.strings للتطبيق. يتيح هذا إرسال حمولة بدون نص بلغة محددة — يقوم التطبيق باستبدال الترجمة.
بدءاً من iOS 15، قدمت Apple آلية وضع التركيز (Focus Mode)، والتي تتطلب من المطور تحديد مستوى انقطاع الإشعار. interruption-level يقبل القيم: passive (بدون صوت، بدون تنشيط الشاشة)، active (سلوك قياسي)، time-sensitive (يخترق وضع التركيز، يتطلب تصريحاً خاصاً) و critical (حالات طبية/طارئة). يساعد مفتاح relevance-score (0–1) نظام Focus في ترتيب الإشعارات داخل فئة واحدة.
يقوم مفتاح thread-id بتجميع الإشعارات في مركز الإشعارات. جميع الإشعارات ذات thread-id نفسه تظهر كمجموعة واحدة يمكن للمستخدم توسيعها. هذا مفيد بشكل خاص لتطبيقات المراسلة، حيث تتجمع رسائل جهة اتصال واحدة معًا، أو للتطبيقات التي ترسل العديد من الإشعارات من نفس النوع.
الحقول المخصصة هي أي مفاتيح خارج قاموس aps يضيفها المطور لنقل بيانات إضافية إلى الجهاز. يدرجها الخادم في كائن JSON الأصلي للحمولة، ويسترجعها التطبيق عبر userInfo في UNNotificationContent. يجب ألا تتضاعف الحقول المخصصة مع أسماء مفاتيح aps لتجنب تعارضات أثناء التحليل.
القيد الرئيسي هو أن الحجم الإجمالي للحمولة يجب ألا يتجاوز 4096 بايت. الحقول المخصصة تتنافس على هذا الحد مع مفاتيح aps الإلزامية، لذا من المهم تقليل حجم البيانات المنقولة. استخدم أسماء مفاتيح قصيرة (مثالاً «uid» بدلاً من «user-id»)، تجنب هياكل JSON كبيرة وارسل فقط معرفات بدلاً من كائنات بيانات كاملة.
تأتي الحقول المخصصة من الخادم ولا يجب الثقة بها دون تحقق. تحقق دائماً من أنواع وقيم الحقول المخصصة عند التحليل: تحقق من وجود المفتاح عبر الربط الاختياري، حول إلى النوع المتوقع باستخدام as? String/Int/Dictionary وعالج حالة عدم وجود القيمة. لا تستخدم أبداً force unwrap (!) لبيانات الحمولة — قد يرسل الخادم بيانات غير صالحة، مما يؤدي إلى تعطل التطبيق.
{
"aps": {
"alert": {
"title": "رسالة جديدة",
"body": "مرحباً! كيف حالك؟"
},
"badge": 5,
"sound": "default",
"category": "message",
"thread-id": "chat_4521",
"mutable-content": 1
},
"sender-id": "user_789",
"chat-id": "chat_4521",
"message-type": "text",
"image-url": "https://cdn.example.com/img.jpg"
}
استخدم نمط تسمية موحد للحقول المخصصة في جميع حمولات المشروع. kebab-case (message-type) أو camelCase (messageType) — كلا النهجين مقبولان، ولكن الاتساق داخل المشروع مهم. تجنب الأسماء الطويلة: «uid» بدلاً من «user-identifier»، «img» بدلاً من «profile-image-url». كل حرف في اسم المفتاح يستهلك بايتاً واحداً من حد 4096.
السيناريوهات المختلفة لإشعارات push تتطلب تركيبات مختلفة من المفاتيح في الحمولة. دعنا نستعرض عدة أمثلة نموذجية: إشعار نصي بسيط، إشعار محلي، إشعار صامت وإشعار غني بمرفق وسائطي.
حمولة أساسية بنص وصوت — أدنى تكوين لعرض إشعار للمستخدم. التنبيه كنص يقدِّم رسالة قصيرة، و sound default يشغل صوت النظام القياسي. Badge اختياري ويضبط العداد على أيقونة التطبيق. يتم إضافة category و thread-id للتجميع والتفاعلية.
{
"aps": {
"alert": "تذكير: اجتماع خلال 15 دقيقة",
"badge": 3,
"sound": "default"
}
}
لإرسال إشعارات إلى أجهزة بلغات مختلفة، استخدم مفاتيح التوطين بدلاً من نص محدد. title-loc-key يشير إلى مفتاح في Localizable.strings للتطبيق، و title-loc-args يقدم الوسائط. يتيح هذا إرسال حمولة واحدة إلى جميع الأجهزة، ويعرض التطبيق النص باللغة المناسبة.
{
"aps": {
"alert": {
"title-loc-key": "NEW_MESSAGE_TITLE",
"title-loc-args": ["آنا"],
"loc-key": "NEW_MESSAGE_BODY",
"loc-args": ["مرحباً!"]
},
"sound": "message.caf"
}
}
للمزامنة في الخلفية دون عرض إشعار، استخدم content-available: 1 بدون alert. الحقول المخصصة تحدد نوع العملية والبيانات للمعالجة. يقوم النظام بتنشيط التطبيق في الخلفية، ويستدعي didReceiveRemoteNotification مع fetchCompletionHandler، ويقوم التطبيق بتنفيذ المزامنة.
{
"aps": {
"content-available": 1
},
"sync-type": "invalidate-cache",
"timestamp": "2026-07-03T12:00:00Z"
}
لعرض مرفق وسائطي، يلزم mutable-content: 1 لتنشيط Service Extension ورابط صورة في حقل مخصص. mutable-content: 1 يشير للنظام بتشغيل UNNotificationServiceExtension، الذي يقوم بتنزيل الصورة من الرابط ويضيفها كـ UNNotificationAttachment. تحدد category فئة مسجلة لعرض أزرار الإجراء.
{
"aps": {
"alert": {
"title": "منتج جديد",
"body": "تصفّح المجموعة الجديدة"
},
"category": "product",
"mutable-content": 1
},
"media-url": "https://cdn.example.com/product.jpg"
}
UNNotificationContent.userInfo يحتوي على قاموس كامل للحمولة المستلمة بعد معالجة النظام. تصل التطبيق إلى الحمولة في مفوض UNUserNotificationCenter عند استلام إشعار (في المقدمة)، عند النقر على إشعار، وكذلك في Service Extension و Content Extension. التحليل الصحيح ضروري لاستخراج البيانات المخصصة وتحديد الإجراءات التالية.
عندما ينقر المستخدم على إشعار، يستدعي النظام طريقة didReceive response في UNUserNotificationCenterDelegate. response.notification.request.content.userInfo يحتوي على الحمولة الكاملة. يستخرج المطور الحقول المخصصة، يحدد نوع الإجراء (على سبيل المثال، فتح محادثة، الانتقال إلى منتج) ويقوم بتنشيط التنقل المناسب في التطبيق.
func userNotificationCenter(
_ center: UNUserNotificationCenter,
didReceive response: UNNotificationResponse,
withCompletionHandler completionHandler: @escaping () -> Void
) {
let userInfo = response.notification
.request.content.userInfo
guard let chatId = userInfo["chat-id"] as? String
else {
completionHandler()
return
}
let messageType = userInfo["message-type"]
as? String ?? "text"
NavigationRouter.shared.navigate(
to: .chat(chatId: chatId,
messageType: messageType))
completionHandler()
}
تستلم Service Extension الحمولة قبل عرض الإشعار ويمكنها تعديلها. التحقق من الحمولة هو الخطوة الأولى في didReceive: تحقق من وجود الحقول المخصصة الإلزامية، تحقق من صلاحية رابط المرفق وتحقق من أنواع البيانات. إذا كانت الحمولة غير صالحة، استدعُ completion handler مع المحتوى الأصلي فوراً لتجنب إضاعة الوقت في معالجة غير ضرورية.
لتصحيح إشعارات push في الإنتاج، استخدم تسجيلاً منظماً للحمولات. OSLog يسمح بتسجيل الحمولة بفئة «notifications» على مستوى debug. على جانب الخادم، راقب استجابات APNS: الاستجابة الناجحة تحتوي على apns-id لمطابقة الحمولة المرسلة، بينما يشير خطأ 400 إلى JSON غير صالح أو تجاوز الحد الأقصى.
الأسئلة الشائعة
الحد الأقصى لحجم الحمولة هو 4096 بايت لإشعارات push العادية و 5120 بايت لدفع VoIP (PushKit). عند تجاوز هذا الحد، يعيد APNS خطأ 400 Bad Request. يتم حساب الحجم بالبايتات، ليس بالأحرف — مراعاة ترميز UTF-8.
استخدم المفاتيح loc-key، title-loc-key، loc-args و title-loc-args داخل alert. يقوم التطبيق باستبدال الترجمة من Localizable.strings الخاصة به حسب لغة الجهاز. يتيح هذا إرسال حمولة واحدة إلى جميع الأجهزة بغض النظر عن لغتها.
content-available ينشط التطبيق في الخلفية لمعالجة البيانات (إشعار صامت) بدون عرض إشعار. mutable-content ينشط Service Extension لتعديل المحتوى قبل العرض. يمكن استخدام كلا المفتاحين معًا للمعالجة في الخلفية وتعديل الإشعار لاحقاً.
استخدم APNS Sandbox للاختبار وتحقق من استجابة HTTP لخادم Apple: 200 OK تعني توصيلاً ناجحاً. للتحقق من البنية، استخدم مخططات JSON في خط التوزيع المستمر CI/CD. في Xcode، أرسل إشعارات اختبارية عبر المحاكي باستخدام xcrun simctl push.
apns-id هو معرف فريد لإشعار push في نظام APNS، يعاد في الاستجابة عند الإرسال الناجح. يستخدم لتتبع التوصيل عبر Logs API وللتصحيح. يجب على الخادم تخزين apns-id لكل إشعار مرسل.
الملخص
سنقوم بتطوير تطبيق جوال جاهز
تقدم IT Sectr تطبيقات iOS وAndroid للشركات الناشئة والشركات منذ عام 2017. سوف نقدم لك النصح ونقترح أفضل حل.
اقرأ أيضًا