משתמשים מתלוננים שהודעות push מגיעות ללא תמונה — השרת שלח אותה, אבל המכשיר לא מציג כלום. או בהודעות e2e, מופיע "הודעה חדשה" במקום הטקסט עקב הצפנה. טיפול רגיל ב-push לא מספיק. הפתרון הוא Notification Service Extension. אנו יוצרים את ה-Extension הזה מקצה לקצה: מהגדרת ה-target ועד לבדיקות על מכשירים פיזיים.
אילו בעיות Notification Service Extension פותר?
קבצים מצורפים (Media attachments). השרת שולח URL לתמונה, וה-Extension מוריד אותה דרך URLSession, שומר אותה בתיקייה זמנית, יוצר UNNotificationAttachment ומעביר אותה דרך contentHandler. ללא זה, קבצים מצורפים לא יעבדו בהודעות push — המשתמש יראה רק טקסט. זמן ההורדה מוגבל ל-30 שניות, ולכן אנו מגדירים timeout של 20 שניות ל-URLSession עם fallback: אם לא הספקנו, אנו מציגים את ההודעה ללא תמונה, ולא מפילים את ה-Extension.
הצפנה מקצה לקצה. ה-payload מגיע מוצפן, ה-Extension מפענח אותו עם מפתח מה-Keychain ומחליף לטקסט קריא. בהודעות e2e, זו הדרך היחידה להציג את תוכן ההודעה מבלי לחשוף מפתחות בשרת. לשיתוף מפתחות, אנו משתמשים ב-App Groups ו-Keychain Sharing עם קבוצת גישה משותפת.
אנליטיקת מסירה. ה-Extension שולח בקשה fire-and-forget לשרת בעת קבלת ההודעה — ומתעד אירוע delivered. UIApplicationDelegate.userNotificationCenter(_:didReceive:) מופעל רק בלחיצה, בעוד ה-Extension מופעל מיד עם המסירה. זה נותן מדדים מדויקים.
איך ליישם הצפנה מקצה לקצה ב-Notification Service Extension?
תהליך הפענוח מורכב מכמה שלבים:
- קבלת ה-payload המוצפן מ-
request.content.userInfo. - חילוץ המפתח מה-Keychain המשותף (הגדרת Keychain Sharing עם האפליקציה הראשית).
- ביצוע פענוח (לדוגמה, AES-GCM) ויצירת גוף ההודעה הקריא.
- העברת התוכן המעודכן דרך
contentHandler.
גישה זו בטוחה יותר מפענוח בצד השרת: המפתח אף פעם לא עוזב את המכשיר. אנו משתמשים בשיטה זו בהודעות עם הצפנה מקצה לקצה, שבהן לשרת אין גישה לתוכן ההודעה.
איך אנו מיישמים את ה-Extension: דוגמה עם קובץ מצורף
הנה קוד טיפוסי לטיפול:
override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) {
self.contentHandler = contentHandler
bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent)
// скачиваем attachment, при ошибке — contentHandler(bestAttemptContent!)
}
override func serviceExtensionTimeWillExpire() {
// вызывается за мгновение до таймаута — показываем что есть
if let contentHandler, let content = bestAttemptContent {
contentHandler(content)
}
}ה-Extension פועל בתהליך נפרד ואין לו גישה ישירה לנתוני האפליקציה הראשית. לצורך החלפה, אנו משתמשים ב-App Groups: UserDefaults(suiteName: "group.com.example.app") ו-FileManager עם ה-group container. Keychain Sharing מוגדר דרך kSecAttrAccessGroup עם אותו מזהה קבוצה.
למה ה-Extension לא עובד בסימולטור ומה לעשות בנידון
הודעות push של APNs לא נמסרות לסימולטור. לבדיקות, השתמשו במכשיר פיזי או הדמו הודעות מקומיות דרך Xcode. אנו מבטיחים פעולה תקינה על מכשירים פיזיים לאחר הגדרת provisioning profiles ו-entitlements.
השוואת תרחישים: טבלת זמן ומורכבות
| תרחיש | זמן יישום | מורכבות |
|---|---|---|
| קובץ מצורף | יום אחד | נמוכה |
| פענוח payload | יומיים | בינונית |
| אנליטיקת מסירה | יום אחד | נמוכה |
| משולב (3+ לוגיקות) | 3–4 ימים | גבוהה |
רשימת טעויות נפוצות בהגדרת Notification Service Extension
לחצו להרחבת הרשימה
- שכחתם להוסיף את היכולת App Groups ל-target של ה-Extension.
- לא הגדרתם provisioning profile עבור ה-Extension (App ID נפרד).
- שימוש בסימולטור לבדיקת push — הודעות לא מגיעות.
- לא הגדרתם timeout ל-URLSession — ה-Extension עלול לקרוס עם שגיאה.
- Keychain Sharing לא עובד ללא קבוצת גישה משותפת עם האפליקציה הראשית.
השוואת גישות: קובץ מצורף דרך Notification Service Extension לעומת יצירה בצד השרת
| גישה | עיכוב במסירה | צריכת תעבורה | גמישות |
|---|---|---|---|
| ה-Extension מוריד מדיה | 0.5–2 שניות הורדה | תעבורה רק במכשיר | כל גודל ופורמט |
| השרת יוצר push עם מדיה | ללא עיכוב | תעבורה כפולה (שרת→APNs→מכשיר) | מוגבל ל-10 MB |
Notification Service Extension עדיף אם צריך להציג תמונות גדולות או וידאו — חוסך עד 40% תעבורה בהשוואה ליצירה בצד השרת.
מה כלול בעבודה
- יצירה והגדרה של ה-target של Notification Service Extension ב-Xcode
- יישום לוגיקה: קובץ מצורף, פענוח או אנליטיקה
- הגדרת App Groups ו-Keychain Sharing להחלפת נתונים
- בדיקה על מכשיר פיזי (ה-Extension לא עובד בסימולטור עבור push של APNs)
- הכנת entitlements ו-provisioning profiles עבור ה-target של ה-Extension
לוח זמנים ועלות
לוח זמנים: מיום אחד (תרחיש בודד) ועד 3–4 ימים (פתרון מקיף). העלות מחושבת באופן אישי — צרו קשר להערכת הפרויקט שלכם. הזמינו יישום של ה-Extension וקבלו אחריות לאיכות: למהנדסים שלנו ניסיון רב בפיתוח iOS והסמכת Apple. כתבו לנו — נציע את הפתרון האופטימלי.
Apple Developer Documentation — UNNotificationServiceExtension מכיל את מפרט ה-API המלא.







