# تتبع تسليم رسائل iOS

توجد [طريقة API](/ar/developer/api-reference/device-api#messagedeliveryevent) في Pushwoosh تتتبع تسليم إشعارات الدفع. لا تدعم تطبيقات iOS هذه الطريقة بشكل افتراضي، لأن إشعارات الدفع على iOS يتم التعامل معها بواسطة نظام التشغيل (OS)، وليس بواسطة Pushwoosh SDK. يمكنك إضافة تتبع التسليم عن طريق إضافة ملحق خدمة الإشعارات (Notification Service Extension) إلى مشروعك. توضح هذه الصفحة كيفية تنفيذ تتبع تسليم الرسائل لتطبيقات iOS.

<Aside>
يتطلب Pushwoosh iOS SDK 7.x، الذي يدعم iOS 13.0 والإصدارات الأحدث.
</Aside>

<Aside type="note">
منذ إصدار Pushwoosh iOS SDK 7.1.0، أصبح التكامل الموصى به هو الفئة الأساسية `PushwooshNotificationServiceExtension` الجاهزة للاستخدام كما هو موضح أدناه. تقوم هذه الفئة بإرسال حدث تسليم الرسالة، وتعيين الشارة، وتنزيل المرفقات الوسائط، وتتعامل مع الحل الاحتياطي الإلزامي `serviceExtensionTimeWillExpire` نيابة عنك. لا تزال واجهة برمجة التطبيقات `PWNotificationExtensionManager` الأقدم تعمل ولكنها مهملة - انظر [التكامل القديم](#legacy-integration).
</Aside>

## إضافة ملحق خدمة الإشعارات

1. في Xcode، اختر **File** > **New** > **Target...**

2. اختر **Notification Service Extension** واضغط على **Next.**

<img src="/ios-push-notifications-ios-message-delivery-tracking-1.webp" alt="محدد قوالب الهدف في Xcode مع تحديد ملحق خدمة الإشعارات"/>

3. أدخل اسم المنتج واضغط على **Finish.**

<Aside type="caution">
لا تختر **Activate** في مربع الحوار الذي يظهر بعد الضغط على **Finish**.
</Aside>

4. اضغط على **Cancel** في نافذة **Activate scheme**.

<img
  src="/ios-push-notifications-ios-message-delivery-tracking-2.webp"
  alt="نافذة Activate scheme مع تمييز Cancel"
  style={{ display: "block", margin: "0 auto", maxWidth: "40%", height: "auto" }}
  width="400"
/>

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

## الاعتماديات لملحق خدمة الإشعارات (CocoaPods فقط)

إذا كنت تستخدم Swift Package Manager لإدارة الاعتماديات، يمكنك تخطي هذه الخطوة، حيث تتم إضافة الاعتماديات تلقائيًا.

افتح ملف `Podfile` الخاص بك وأضف الاعتمادية للهدف:

```ruby title="Podfile"
target 'NotificationServiceExtension' do
  use_frameworks!
  pod 'PushwooshXCFramework'
end
```

قم بتشغيل الأوامر التالية في الطرفية لتثبيت الاعتماديات:

```shell
rm -rf Podfile.lock
pod deintegrate
pod setup
pod repo update
pod install
```

## إضافة كود لتتبع أحداث تسليم الرسائل

اجعل ملحقك فئة فرعية من `PushwooshNotificationServiceExtension`. فئة فرعية فارغة كافية: يقوم Pushwoosh بإرسال حدث تسليم الرسالة، وتعيين الشارة، وتنزيل المرفقات الوسائط، والتعامل مع الحل الاحتياطي لانتهاء المهلة تلقائيًا.

استبدل المحتويات التي تم إنشاؤها لملف **NotificationService** الخاص بك:

<Tabs>
<TabItem label="Swift">

```swift
import UserNotifications
import PushwooshFramework

class NotificationService: PushwooshNotificationServiceExtension {}
```

</TabItem>

<TabItem label="Objective-C">

```objective-c
#import <PushwooshFramework/PushwooshNotificationServiceExtension.h>

@interface NotificationService : PushwooshNotificationServiceExtension

@end

@implementation NotificationService

@end
```

</TabItem>
</Tabs>

<Aside type="tip">
إذا لم تكن بحاجة إلى أي كود مخصص، يمكنك تخطي الملف المصدري بالكامل وتوجيه `NSExtensionPrincipalClass` في Info.plist الخاص بالملحق إلى `PushwooshNotificationServiceExtension` مباشرة.
</Aside>

### معرّف التطبيق (App ID)

منذ الإصدار 7.1.0، يرث الملحق `Pushwoosh_APPID` (والمفاتيح الأخرى التي تبدأ بـ `Pushwoosh_*`) من Info.plist الخاص بالتطبيق المضيف، لذا لم تعد بحاجة إلى تكراره في الملحق. أضف `Pushwoosh_APPID` إلى Info.plist الخاص بالملحق فقط عندما تريد تجاوز قيمة المضيف:

```xml title="NotificationService/Info.plist"
<key>Pushwoosh_APPID</key>
<string>XXXXX-XXXXX</string>
```

<Aside type="note">
في إصدارات Pushwoosh iOS SDK الأقدم من 7.1.0، لا يرث الملحق التكوين من التطبيق المضيف. في تلك الإصدارات، يجب عليك إضافة `Pushwoosh_APPID` إلى Info.plist الخاص بالملحق.
</Aside>

### مجموعة التطبيقات (App Group) (الشارة والبروكسي العكسي)

مجموعة التطبيقات (App Group) المشتركة بين التطبيق والملحق ضرورية لمزامنة عدد الشارات وقراءة إعدادات البروكسي العكسي التي يخزنها التطبيق المضيف.

1. أضف إمكانية **App Groups** إلى هدف الملحق وقم بتمكين نفس المجموعة هناك كما في التطبيق المضيف. هذا مطلوب - بدون الحاوية المشتركة لا يمكن مزامنة عدد الشارات وإعدادات البروكسي العكسي.

2. قم بتوفير اسم مجموعة التطبيقات. مثل `Pushwoosh_APPID`، يرث الملحق `PW_APP_GROUPS_NAME` من Info.plist الخاص بالتطبيق المضيف منذ الإصدار 7.1.0، لذا إذا قمت بتعيينه هناك بالفعل للشارات، فلن تحتاج إلى إضافته إلى الملحق. قم بتعيينه في Info.plist الخاص بالملحق فقط لتجاوز قيمة المضيف، أو قم بتوفيره برمجيًا عن طريق تجاوز `pushwooshAppGroupsName`.

```xml title="App Info.plist"
<key>PW_APP_GROUPS_NAME</key>
<string>group.com.example.app</string>
```

<Aside type="caution">
إذا كان التطبيق المضيف يستخدم بروكسي عكسي (`Pushwoosh_ALLOW_REVERSE_PROXY`)، فإن الملحق يحتاج إلى مجموعة التطبيقات هذه لقراءة عنوان URL للبروكسي الذي قام التطبيق بتخزينه هناك. بدونها، يتم تعليق حدث التسليم بدلاً من إرساله مباشرة، متجاوزًا البروكسي.
</Aside>

## تخصيص الإشعار (اختياري)

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

قم بتعيين مجموعة التطبيقات برمجيًا بدلاً من استخدام مفتاح Info.plist:

```swift
override func pushwooshAppGroupsName() -> String? {
    "group.com.example.app"
}
```

قم بتشغيل تحضير غير متزامن قبل أن يعالج Pushwoosh الدفع - على سبيل المثال، الجلب المسبق لوسائط Push Stories - دون تجاوز `didReceive` القياسي. قم باستدعاء `completion` مرة واحدة بالضبط، على الخيط الرئيسي:

```swift
override func pushwooshPrepare(for request: UNNotificationRequest,
                              completion: @escaping () -> Void) {
    // async work here
    completion()
}
```

قم بتعديل المحتوى قبل عرضه عن طريق تجاوز `didReceive`. قم باستدعاء `super` مع معالج المحتوى الخاص بك، وقم بتعديل المحتوى بداخله، ثم قم بتمريره إلى المعالج الأصلي:

```swift
override func didReceive(_ request: UNNotificationRequest,
                         withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) {
    super.didReceive(request) { content in
        let mutable = (content.mutableCopy() as? UNMutableNotificationContent) ?? content
        // customize `mutable` here
        contentHandler(mutable)
    }
}
```

## التكامل القديم

<Aside type="caution">
`PWNotificationExtensionManager` مهمل منذ الإصدار 7.1.0. استخدمه فقط إذا لم تتمكن من إنشاء فئة فرعية من `PushwooshNotificationServiceExtension` - على سبيل المثال، ملحق يمتد بالفعل من فئة أساسية لـ SDK آخر، أو غلاف متعدد المنصات (React Native, Flutter, Unity). يجب أن تستخدم التكاملات الجديدة الفئة الأساسية المذكورة أعلاه.
</Aside>

تقوم واجهة برمجة التطبيقات منخفضة المستوى هذه بتشغيل نفس المعالجة (حدث التسليم، الشارة، المرفقات) من `UNNotificationServiceExtension` عادي:

<Tabs>
<TabItem label="Swift">

```swift
import UserNotifications
import PushwooshFramework

class NotificationService: UNNotificationServiceExtension {

    override func didReceive(_ request: UNNotificationRequest,
                             withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) {
        PWNotificationExtensionManager.sharedManager()
            .handleNotificationRequest(request, contentHandler: contentHandler)
    }
}
```

</TabItem>

<TabItem label="Objective-C">

```objective-c
#import "PWNotificationExtensionManager.h"

@interface NotificationService : UNNotificationServiceExtension

@end

@implementation NotificationService

- (void)didReceiveNotificationRequest:(UNNotificationRequest *)request
                   withContentHandler:(void (^)(UNNotificationContent *))contentHandler {
    [[PWNotificationExtensionManager sharedManager] handleNotificationRequest:request
                                                              contentHandler:contentHandler];
}

@end
```

</TabItem>
</Tabs>

## شاركنا ملاحظاتك

تساعدنا ملاحظاتك في إنشاء تجربة أفضل، لذلك نود أن نسمع منك إذا كان لديك أي مشاكل أثناء عملية تكامل SDK. إذا واجهت أي صعوبات، فلا تتردد في مشاركة أفكارك معنا [عبر هذا النموذج](https://docs.google.com/forms/d/e/1FAIpQLSd_0b8jwn-V_JmoPLIxIFYbHACCQhrzidOZV3ELywoQPXRSxw/viewform).