عندما يتم تسليم البريد: مكافحة فقدان إعلامات الدفع في نظام التشغيل iOS

من جانب المستخدم ، يعد عميل البريد الإلكتروني تطبيقًا بسيطًا. يضحك مطورو Yandex.Mail أن هناك ثلاث شاشات فقط في التطبيق: قائمة من الرسائل ؛ ارسال خطاب عن الشاشة.

ولكن الكثير من الأشياء المثيرة للاهتمام تحدث تحت الغطاء. مثل العديد من تطبيقات الأجهزة المحمولة ، يستخدم Mail إعلامات الدفع للتفاعل مع المستخدمين. مثل العديد من تطبيقات iOS ، يفقد Mail بعض الإشعارات نظرًا لطبيعة خدمة إعلام Apple Push.

سيثبت Asya Sviridenko ، رئيس مجموعة Yandex.Mail iOS ، أنه حتى مع وجود قيود على النظام ، من الممكن والضروري التعامل مع فقدان إشعارات الدفع إذا كانت ضرورية لتطبيقك. ينطبق هذا على Mail ، لأن إعلامات الدفع الخاصة بالرسائل الجديدة هي ما يقوم المستخدم بتثبيت التطبيق من أجله. إذا لم يكن تسليم إشعارات الدفع أمرًا بالغ الأهمية بالنسبة للتطبيق الخاص بك ، فلا يزال من المثير للاهتمام معرفة أي الدراجات التي تراكمت على Yandex.Mail المحمول.


يتعلق الأمر بالإشعار عن بعد ، أي الإشعارات التي تأتي من الخادم من خلال APNs (خدمة إعلام Apple Push). لن نتطرق إلى الإشعارات المحلية ونتحدث عن:

  • كيف تبدو واجهة برمجة التطبيقات للتعامل مع إشعارات الدفع. فكر في مخطط تسليم إشعار الدفع وأين يمكن أن تحدث خسائر في هذا المخطط.
  • كيف قررت التعامل مع الخسائر في Yandex.Mail - قائمة انتظار الإشعارات.
  • كيفية تسجيل الدخول وما الصعوبات الأخرى التي يمكن مواجهتها.

ما لدينا وحيث نخسر


الآن تعد واجهة برمجة التطبيقات للتعامل مع إشعارات الدفع أمرًا قويًا بدرجة كافية تتيح لك القيام بالعديد من الأشياء المثيرة للاهتمام. ولكن هذا لم يكن الحال دائما.



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

لقد مر الوقت الكافي منذ ذلك الحين.



بالنسبة لنا ، كمطورين ، بدأ كل شيء في نظام التشغيل iOS 3 عندما أصبحت إعلامات الدفع متاحة لمكتبات الجهات الخارجية.

ظهر مركز الإشعارات في نظام التشغيل iOS 5 ، وتوقفت إشعارات الدفع عن الذهاب إلى أي مكان ، والآن تظل في مركز الإشعارات ، حيث يمكن عرضها مرة أخرى.

IOS 6 قدم لا تزعج . لدى المستخدم الفرصة لتعيين الفترة الزمنية التي لا يريد خلالها تلقي الإعلامات.

تتعلق هذه التغييرات أساسًا بكيفية عمل المستخدم مع إشعارات الدفع ، وكيف يمكن أن يجعل حياته أكثر راحة ، وليس كيف يمكن للمطورين التأثير على الإشعارات.

بالنسبة للمطورين ، كان iOS 8 حدثًا مهمًا وظهور Notification Action ، والذي سمح بتنفيذ إجراءات خاصة بتطبيق معين عن طريق إعلامات الدفع.

يقدم IOS 10 امتداد خدمة الإعلام وتمديد محتوى الإعلام . الأول يتيح لك تعديل إشعار الدفع قبل أن يتم عرضه على المستخدم. والثاني هو إظهار بعض واجهة المستخدم عن طريق إعلام الدفع في إعلام الدفع ، والذي ، على سبيل المثال ، يمكنك عرض معلومات أكثر تفصيلاً. في نظام التشغيل iOS 10 ، كانت واجهة المستخدم هذه غير قابلة للنقر - يمكنك مشاهدتها ، ولا يمكنك لمسها.

قدم IOS 11 إعدادات خصوصية الإخطار . الآن يمكن للمستخدم الانتقال إلى الإعدادات والإشارة إلى ما إذا كان يريد عرض محتويات الإعلامات الواردة. هذه خطوة كبيرة نحو الأمن. استغرق الأمر 8 إصدارات فقط من نظام التشغيل iOS لفهم أن المستخدمين لا يريدون أن تظهر المعلومات الشخصية بشكل مفاجئ على جهاز iPhone الموجود على الطاولة.

في نظام التشغيل iOS 12 ، أصبح من الممكن تجميع إشعارات الدفع بواسطة معرف مؤشر الترابط ، وأصبحت واجهة المستخدم التي تلقيناها في نظام التشغيل iOS 10 مع امتداد محتوى الإشعار قابلة للنقر. يمكنك الآن إضافة أزرار والتحكم بالإيماءات هناك - كل ذلك يساعد المستخدم على التفاعل مع واجهة المستخدم.

دفع الإخطارات اليوم


كما ترون ، قطعت إشعارات الدفع شوطًا طويلًا ، واليوم يمكنك بمساعدتهم فعل الكثير من الأشياء.

الرسائل النصية والتعريب


كما كان من قبل ، يمكننا إرسال رسائل نصية في إشعار دفع ، لكن الآن يمكنك تحديد مفاتيح التعريب.

"aps" : { "alert" : { "title" : "New Mail", "subtitle-loc-key" : "alert_subtitle_localization_key", "loc-key" : "alert_body_localization_key", } } 

إذا قمت بتحديد subtitle-loc-key و loc-key في إشعار الحمولة النافعة ، فعندما يصل إشعار الدفع إلى الجهاز ، سيتم العثور على القيم اللازمة في ملف Localizable.string للتطبيق وسيظهر المستخدم رسالة مترجمة.

تنبيه صوتي وحرج


كما كان من قبل ، يمكنك إضافة أصوات لإعلامات الحمولة النافعة.

 "aps" : { "sound" : { "critical" : 1, "name" : "bingbong.aiff", "volume" : 1.0, } } 

IOS 12 لديه تنبيه حرج. هذه هي الأصوات التي سيتم تشغيلها حتى لو كان المستخدم في وضع عدم الإزعاج.

عادةً ، لا يحتاج المستخدم ، على سبيل المثال ، إلى تطبيق اشتراك مجلة في الليل للإبلاغ عن إصدار رقم جديد. لذلك ، تقوم Apple بتقييد التطبيقات التي يمكنها استخدام التنبيه الحرج. إذا كان تطبيقك يعمل مع الصحة أو السلامة أو كنت تعتقد أن التنبيه الحرج هو شيء يمكن أن يساعد المستخدمين حقًا على التفاعل مع التطبيق الخاص بك ، فاكتب إلى Apple. ربما سيسمح لك باستخدام هذه الوظيفة.

الإخطارات الصامتة


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

 "aps" : { "content-available" : 1 //   alert, sound  badge   payload } 

لكي يصبح إشعار الدفع صامتًا ، يجب أن تحدد في الحمولة النافعة: "content-available" : 1 . ولا تحدد مفاتيح التنبيه والصوت والشارات في الحمولة - فهي غير مجدية تمامًا لإشعارات الدفع التي لن تظهر للمستخدم.

مجموعة الإخطار


لتجميع الرسائل ، يجب عليك تحديد "معرف الموضوع" في الحمولة النافعة. يمكن أن يحتوي على عدة قيم داخل نفس التطبيق ، إذا كنت تريد التجميع بطرق مختلفة: حسب الحسابات ، بواسطة المستلمين ، حسب الموضوع.

 "aps" : { "thread-id" : "any_thread_identifier" } 

هذا أمر مريح للغاية ، لأن إشعارات الدفع الآن لا تشغل كل المساحة على الشاشة المقفلة ، ولكن يتم تجميعها معًا. إذا لم تكن تستخدم هذه الوظيفة بالفعل ، فقد حان الوقت للبدء.

تغيير الإشعار قبل إظهاره


يمكن تغيير إعلامات الدفع قبل عرضها. للقيام بذلك ، تحتاج إلى إضافة "ملحق محتوى الإعلام" إلى التطبيق وتجاوز طريقة didReceive . في هذه الطريقة ، يمكنك الحصول على محتوى الإشعار وتعديله.

 "aps" : { "mutable-content" : 1 } override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) { guard let mutableContent = request.content.mutableCopy() as? UNMutableNotificationContent else { contentHandler(request.content); return } mutableContent.subtitle = "Got it!" contentHandler(mutableContent) } 

على سبيل المثال ، يمكنك إرسال رابط إلى محتوى الوسائط في الإشعار ، وتنزيل المحتوى في ملحق ، وإرفاق التنزيل الذي تم تنزيله بالإشعار. بعد ذلك ، استكمل المكالمة مع سياق جديد ، وأظهر للمستخدم إشعار دفع ممتد. يمكنك تغيير العنوان والعنوان الفرعي وما إلى ذلك.

هناك حالة أخرى مثيرة للاهتمام وهي أنه يمكنك إرسال إشعار دفع مع سياق مشفر ، إذا كنت تريد حماية البيانات بشكل إضافي ، ولم تطلع عليها Apple. في امتداد محتوى الإشعارات ، يمكنك فك تشفيرها وإظهار بيانات المستخدم التي تم فك تشفيرها بالفعل.

محتوى الإخطار المخفي


في نظام iOS 11 ، أصبح من الممكن إخفاء محتويات إشعارات الدفع ، ونحن ، كمطورين ، لا يمكننا التأثير في هذا بأي شكل من الأشكال. إذا حدد المستخدم "إخفاء محتوى الإشعار" ، فسيتم إخفاؤه بطريقة أو بأخرى. كل ما يمكننا فعله هو من خلال UNNotificationCategory لتحديد عنصر نائب سيتم عرضه بدلاً من المحتوى (افتراضيًا ، هذا إخطار) ، ولتحديد ما إذا كان سيتم عرض العنوان أو العنوان الفرعي.

 let commentCategory = UNNotificationCategory(identifier: "comment-category", actions: [], intentIdentifiers: [], hiddenPreviewsBodyPlaceholder: NSString.localizedUserNotificationString(forKey:"COMMENT_KEY",arguments: nil), options: [.hiddenPreviewsShowTitle]) 

خطوات الإخطار دون تشغيل التطبيق


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

 "aps" : { "category" : "message" } let action = UNNotificationAction(identifier:"reply", title:"Reply", options:[]) let category = UNNotificationCategory(identifier: "message", actions: [action], minimalActions: [action], intentIdentifiers: [], options: []) UNUserNotificationCenter.current().setNotificationCategories([category]) 

الإخطارات الغنية


في هذا الملحق ، يمكنك معالجة الإجراءات الإضافية التي أضفتها إلى إشعار الدفع وعرض واجهة المستخدم المخصصة.

للقيام بذلك ، تحتاج إلى إضافة "ملحق محتوى الإعلام" إلى التطبيق ، وتحديد فئة فيه يرث من UNNotificationContentExtension ، ثم العمل معه كما هو الحال مع UIViewController العادية.

 class NotificationViewController: UIViewController, UNNotificationContentExtension { @IBOutlet var userLabel: UILabel? func didReceive(_ notification: UNNotification) { let content = notification.request.content self.title = content.title let userInfo = content.userInfo self.userLabel?.text = userInfo["video-user"] as? String } } 

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

نظام تسليم الإشعارات بالدفع


تعرف على مقدار ما يمكنك فعله باستخدام إشعارات الدفع في iOS. من الإصدار إلى الإصدار ، لدينا المزيد والمزيد من الوظائف الجديدة ، لكن نظام تسليم إعلام الدفع الآن هو نفسه تمامًا كما كان في نظام iOS 3.



قد يعتقد المرء أن مخطط تسليم إشعار الدفع كان جيدًا من البداية ، لكنه ليس كذلك.

هناك ثلاث نقاط رئيسية في نظام تسليم إشعار الدفع:

  • المزود الذي ينشئ إعلامات الدفع الحمولة النافعة.
  • APNs - خدمة Apple Push Notification Service ، التي تقدم إشعارًا ؛
  • جهاز iOS وتطبيقك.

سوف أتخطى الجزء الخاص بكيفية التسجيل واستلام الرمز المميز ومكان إرساله. لنفترض أن لدينا كل هذا. ماذا يحدث بعد ذلك؟

  • يقوم المزود بتوليد حمولة وإرسالها إلى APNs.
  • APNs ترسلها إلى الجهاز.
  • يرى المستخدم رسالة دفع على جهازه.

يستخدم البريد والعديد من التطبيقات الأخرى نظام تسليم إعلام الدفع المتقدمة. تتم إضافة ملحق خدمة الإشعارات ، والذي يستقبل إشعارات الدفع "mutable-content" : 1 . ينقسم الموفر إلى خادم يتعامل مع منطق الواجهة الخلفية للتطبيق ، والمزود نفسه ، الذي يولد حمولة ويتعامل مع الاشتراكات.

في Yandex ، يطلق على الموفر الذي يشكل الحمولة النافعة XIVA. XIVA هي قاعدة بيانات الاشتراك. يستخدم البريد XIVA للعمل مع إشعارات الدفع كمكتبة تابعة لجهة خارجية.

في Mail ، يتم تنظيم العمل باستخدام الاشتراكات بشكل تافه تمامًا. نحن لا نوقع فقط على طلب الإخطارات ، لدينا حساب متعدد. يمكننا تسجيل حسابات مختلفة ، أو ضمن حساب واحد ، اختيار المجلدات التي يريد المستخدم تلقي الإخطارات وتلك التي لا يريدها. XIVA يتعامل مع كل هذا. تعمل بعض خدمات Yandex الأخرى أيضًا من خلال XIVA: يتم تخزين جميع المعلومات حول التطبيقات والإشعارات والاشتراكات والرموز في XIVA.

أين الخسائر؟


هناك أربعة أسهم في نظام تسليم إعلام الدفع ؛ يمكن أن تحدث الخسائر في ثلاثة من هذه التحولات.

بين الخادم و XIVA ، قد تحدث خسائر في الحالة التالية. تلقى المستخدم خطابًا ، ويعرف الخادم عنه ، ويقوم بإنشاء إشعار وإرساله إلى XIVA. لكن قد يفقد XIVA هذه المعلومات ، على سبيل المثال ، إذا اختار مستخدم في التطبيق "اشتراك" في مجلد معين أثناء عدم الاتصال. ثم لن تتلقى XIVA معلومات حول الاشتراك في المجلد ، وعند وصول الحمولة الصافية ، ستقوم بحذفها ببساطة ولن يرى المستخدم الإشعار.

بين XIVA و APNs ، قد يحدث فقدان الشبكة. بالكاد نستطيع التأثير على الشبكة ، لذلك لن نتناول هذه النقطة.

بين APNs و Extension ، أو APNS و iOS إذا كنت لا تستخدم Extension. هذا هو أكثر أنواع الخسارة شيوعًا. تحدث هذه الخسائر لأن APNs لا تخزن أكثر من دفعة واحدة لكل تطبيق على الجهاز. إذا كان المستخدم غير متصل بالإنترنت ، فإنه يتلقى العديد من الإخطارات ، وعندما يتصل بالإنترنت ، فسوف يرى الرسالة الأخيرة فقط.

هذه هي نفس الخسائر التي لا تسمح لنا بضمان التسليم والاعتماد على إشعارات الدفع. أبل يكتب بوضوح أن التسليم غير مضمون.

بين تطبيق Extension و iOS ، لا يمكن حدوث خسائر ، وتضمن Apple ذلك. إذا كنت تستخدم الامتداد وتجاوزت didReceiveContent مع طريقة الإكمال ، حتى إذا لم تتصل بهذا الإكمال ، فسيظهر الإخطار على أي حال. هذا هو المهم أن نتذكر. لا يجوز لك الاتصال به أو ليس لديك وقت للاتصال به ، ولكن بعد ذلك سيتم عرض الإشعار دون أي تغييرات ، في النموذج الذي يأتي به من APNs.

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

قائمة انتظار الإشعارات


طريقتنا للتعامل مع الخسائر في حزمة APNs و Extension أطلقنا عليها قائمة انتظار الإشعارات.

إذا قمت بضغط القصة بأكملها على عبارة واحدة ، فستكون:
إذا فاتتك إشعار الدفع ، يمكنك طلب ذلك مرة أخرى.



في نظام تسليم الإشعارات لدينا ، يكون جميع المشاركين أنفسهم: XIVA و APNs و Extension. مخطط مبسط يعمل مثل هذا:

  • يقوم XIVA بترقيم إشعارات الدفع التي يعتزم إرسالها إلى APNs ، وعندها فقط يرسل المعلومات.
  • تتلقى الإضافة رقم إشعار الدفع 1 ، وبعد مرور بعض الوقت ، الرقم 3. وهي تتفهم أن بعض البيانات مفقودة.
  • يرسل إلى XIVA طلبًا مع آخر موضع تم استلامه ، فرقًا ويطلب إرسال البيانات المفقودة مرة أخرى.
  • تقوم XIVA بإعادة إرسال إشعار الدفع لأنه يخزن قاعدة بيانات الحمولة وقاعدة بيانات الاشتراك. يتم تخزين جميع الاشتراكات لبعض الوقت ويمكن إعادة طلبها.
  • نعيد الطلب ، نتلقى إشعارًا بالدفع ، ولدينا على العميل جميع الرسائل التي كان يجب على العميل استلامها.

المشكلة الأولى المتوقعة هي الإخطارات المكررة. عندما نعيد طلب رسالة من XIVA ، لا نعرف ما هو في قائمة الانتظار للإرسال ، لأننا نتواصل معها ليس بشكل مباشر ، ولكن من خلال APNs. افترض أننا رأينا أن بعض الإعلامات مفقودة ، وأرسلنا طلبًا إلى XIVA. أرسلت XIVA عبر APNs الحمولة مع إخطار لم يرد عليها. ولكن قبل تلقيناها ، تلقينا حمولة أخرى وأيضًا بتمريرة. طلبوا مرة أخرى - أرسلت XIVA مرة أخرى.

بحيث لا يتم تكرار الإخطارات ، نستخدم apns-طي-id . يتيح هذا الإعداد لجانب iOS انهيار إشعارات الدفع بنفس المعرف. إذا وصلت العديد من إشعارات الدفع التي تحمل نفس معرف apns -apse-id إلى الجهاز ، فسيؤدي ذلك إلى انهيار نظام iOS وسيشاهد المستخدم إشعارًا واحدًا فقط.

XIVA


سوف أخبرك كيف يعمل كل شيء على XIVA ، لأنه من الغريب دائمًا ما يحدث في الواجهة الخلفية.

كانت XIVA موجودة قبل قائمة انتظار الإشعارات وكانت قاعدة بيانات اشتراك. من المهم أن يتم تخزين كل شيء من قبل المستخدمين في قاعدة البيانات:

  • كان المفتاح <service, user> .
  • تم تخزين الحمولة الصافية كقيمة (بيانات حول الحروف في حالة البريد).

أخذت XIVA البيانات من قاعدة البيانات وأرسلت إلى APNs أو خدمة أخرى ، لأنه لا يعمل فقط مع iOS. قررنا إعادة استخدامها.

لقد جئنا إلى فريق التطوير XIVA وطلبنا حقًا قائمة انتظار إشعار الدفع. من حيث المبدأ ، كان لدى XIVA بالفعل كل شيء من أجل هذا: قاعدة البيانات ، TTL للحمولات ، أي لا يتم حذفها على الفور ، ويمكن إعادة توجيهها. الشيء الوحيد الذي كان مفقودًا هو أنه كان من الممكن تهيئة قائمة انتظار الإشعارات بالدفع كجزء من تطبيق XIVA الحالي - إنه ترقيم من طرف إلى طرف.

بالنسبة للترقيم التمريري ، يجب ترقيم إعلامات الدفع حسب الجهاز واسم التطبيق. أي أن الترقيم من طرف إلى طرف مطلوب لجهاز معين ولتطبيق معين من أجل الاعتماد عليه من جانب العميل. لقد قمنا بذلك على النحو التالي: إعادة استخدام قاعدة بيانات XIVA ، لكننا بدأنا في كتابة حمولاتها باستخدام مفتاح مختلف. تعمل apns_queue الآن كخدمة ، مثل user device_id + app_name - نفس البيانات التي تحتاج إلى ترقيم على العميل ، أي key: <apns_queue, device_id + app_name> .

الآن تأخذ XIVA البيانات من قاعدة البيانات الرئيسية وتضعها في قائمة الانتظار عندما تحتاج إلى إرسالها. في هذه المرحلة ، تتلقى الحمولات الصافية ترقيمًا جديدًا ، لأنهم الآن في نفس قاعدة البيانات ، ولكن باستخدام مفتاح مختلف. بالفعل من هناك ، تأخذ XIVA بها وترسلها عبر APNs. في المجموع ، يتلقى العميل ترقيم الحمولة اللازمة.

يستخدم العميل ملحق خدمة الإعلام.

 public override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) { // . . . } 

نعيد تعريف طريقة didReceive ونرى ما جاء من الخادم. نضيف "mutable-content" : 1 إلى جميع إشعارات الدفع بحيث تقع في ملحق ، لأنه لا يمكننا مراعاة ذلك في الحسابات.

علاوة على ذلك ، يوجد في الكود الموجود داخل الطريقة اختبارات مستمرة: ما إذا كانت الحمولة النافعة ضرورية ، أم لا. إذا لم يتم تحليلها ، فهذه الرسالة ليست من XIVA. إذا لم تكن الرسالة من XIVA ، فلن نتمكن من الاستمرار في العمل معها وبكل بساطة ننتهي من خلال الإخطار الوارد من APNs ، لا ننفذ أي حسابات.

 guard let payload = try? self.payloadParser.parsePayload(from: request.content.userInfo) else { //  ,     xiva contentHandler(request.content); return } 

نقوم بتسجيل الدخول ، تحقق مما إذا كان الجهاز قد تغير ، نظرًا لأننا نعرف أنه من الممكن في نظام iOS. بصراحة ، لم نواجه أي تغيير في deviceId ، ولكن فقط في حالة قيامنا بمعالجته ، لأنه إذا تغير ، فلن نتمكن من الوثوق بالأرقام من XIVA.

 self.logger.logNotificationReceived(with: payload) if lastPositionDeviceId != deviceId { // deviceId ,    lastNotificationPosition = nil lastPositionDeviceId = deviceId } 

علاوة على ذلك ، ننظر فيما إذا كان بإمكاننا تلقي بيانات XIVA في هذه الحمولة ، سواء كانت أو لم تكن. إذا لم يكن كذلك ، فاتصل بالمحتوى مرة أخرى

 guard let xivaInfo = payload.xivaInfo else { contentHandler(request.content); return } 

إذا كانت هناك بيانات ، تحقق لمعرفة ما إذا كان الجهاز قد تلقى البيانات أم لا. يرسل XIVA تجزئة الجهاز إلى الحمولة ، إذا تم التحقق منه ومطابقته ، فسنستمر ، لا ، نحن نسمي contentHandler.

 guard isHashCompatible(deviceId: deviceId, deviceIdHash: xivaInfo.deviceIdHash) else { // payload device_id   device_id  contentHandler(request.content); return } 

الكتلة التالية هي معرفة ما إذا كان هناك موضع محفوظ:

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

 guard let lastPos = lastNotificationPosition else { //      lastNotificationPosition = xivaInfo.notificationPosition contentHandler(request.content); return } 

نحن نحسب عدد الإخطارات الفائتة. إذا كان فقدان الصفر على ما يرام ، فلن نفتقد أي شيء.

 let missedMessages = xivaInfo.notificationPosition - lastPos - 1 guard missedMessages > 0 else { //   push–     contentHandler(request.content); return } 

خلاف ذلك ، فإننا نأخذ من XIVA بيانات الموقع - من نفس الترقيم المستمر. علاوة على ذلك ، ننظر إلى ما إذا كانت كمية الفائتة لا تتجاوز قيمة معينة محددة.

 lastNotificationPosition = xivaInfo.notificationPosition guard missedMessages <= repeatMaxCount else { //    ,   contentHandler(buildNewNotification()); return } 

لماذا هذا مطلوب؟ لنفترض أن المستخدم كان غير متصل بالإنترنت لفترة طويلة ، وخلال هذا الوقت تم تجميع مائة رسالة. سنطلب المائة كاملة (الأمر سهل بالنسبة لنا) ، وسوف ترسل XIVA المائة بالكامل ، وسيتلقى المستخدم جميع الإشعارات. حتى لو قمنا بتجميعها بواسطة معرف مؤشر الترابط (وقمنا بتجميعها) ، ومع ذلك ، فلكل إخطار ، سيتم استدعاء هذا الامتداد ، وستمر كل الاختبارات. يبدو من غير المحتمل أن يحتاج المستخدم إلى جميع الإشعارات المائة. لذلك ، نقوم بإنشاء إشعار نكتب فيه أن لديك 100 رسالة لم يرد عليها ، انتقل إلى التطبيق وابحث. ونعرض للمستخدم هذه الرسالة بالضبط ، لأنه يمكننا استبدال إشعارات الدفع.

عندما تنتهي جميع الشيكات ، نرسل طلبًا إلى XIVA: آخر موضع جاء إلينا ، وعدد الرسائل الفائتة. وانظر:

  • في حالة رد XIVA بنجاح: "كل شيء على ما يرام ، سأرسل البيانات" ، نعرض على المستخدم الإخطار الحالي وننتظر حتى يرسل XIVA كل شيء آخر وسيشاهد المستخدم جميع الرسائل التي تم تفويتها.
  • إذا أجاب XIVA بخطأ ما ، فإننا نعرض للمستخدم إشعارًا مخصصًا بأنه فقد الرسائل التي يمكن عرضها في التطبيق.

 self.requestMissedNotifications(lastPosition: xivaInfo.notificationPosition, gap: missedMessages) { result in result.onValue { _ in self.logger.logNotificationProcessed(with: .success) contentHandler(request.content) }.onError { error in self.logger.logNotificationProcessed(with: .failure(error)) contentHandler(buildNewNotification()) } } 

وبالتالي ، فإن التطبيق على العميل يعود إلى عدد كبير من الفحوصات التي يمكننا من خلالها معرفة ما إذا كان يمكننا العمل مع البيانات المستلمة.

قطع الأشجار والصعوبات الأخرى


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

حدود دفع التمديد


أول شيء واجهناه هو قيود تمديد الضغط.

لا يسمى دائما . إذا قمت بإيقاف تشغيل الإشعار الذي يتم رسمه في إعدادات التطبيق (تظل القدرة على تلقي إشعار قيد التشغيل ، ولكن يتم إيقاف تشغيل كل التجسيدات الممكنة) ، فلن يتم استدعاء الامتداد - ولن يتم استدعاء كل المنطق الذي يحتوي على عمليات إعادة حساب ، والأهم من ذلك أن التسجيل. لن نتمكن من معرفة ما هو أهم بالنسبة لنا - ما إذا كان المستخدم قد تلقى إشعارًا أم لا.

دفع تمديد لديه مهلة زمنية . تشير وثائق Apple إلى أنه في غضون 30 ثانية تقريبًا ، يلزمك إكمال الاتصال بإشعار معدل ، وإلا فسيتم عرض الإشعار الأولي.

وأتساءل كيف اكتشفنا ذلك. قمنا بتطبيق ميزة أطلقنا عليها إشعارات الدفع "الجميلة" ، وعناصر الوسائط المرفقة بالإشعارات ، وتغيير العنوان ، والعنوان الفرعي. أثناء الاختبار ، اتضح أن بعض إشعارات الدفع أصبحت جميلة ، في حين بقي الباقي مثل البط القبيح.

بدأنا ننظر إلى الفرق بين إعلامات الدفع هذه ووجدنا أنه لا يوجد فرق ، فقط بالنسبة لبعض تمكنا من استدعاء المكالمة ، ولكن بالنسبة للآخرين لم يكن هناك. , , push- , APNs.

. Apple , , push-extension, , , . , 12 .

Apple Developer Forum , , . , — 10 .

, . AppMetrica. , AppMetrica , Extension . , - .

: Extension .


push-extension UserDefaults. , , AppMetrica.

. . , , . , . , XIVA ( ), , .

, Notification Extension iOS 10 , Extension, , .

AppMetrica : , push-extension . AppMetrica push-, , . , AppMetrica Push SDK .

, . — , . , .



— , , .

, push-, , — .

, , . , …


: , , . , ? - , push-? , ? user experience ?

, 2–3–20 ?

, , , , , , , . , push-. , .

النتائج


Push- iOS . , .. , .

push- ( ) . . XIVA. , , . , , . !

push-extension. , . , .

, . , , , , - . , push- . , , , App Store, , !

AppsConf , 21 22 , .. 50 , . 1 , — .

Source: https://habr.com/ru/post/ar462507/


All Articles