יישום Handoff בין מכשירי iOS

משתמשים עוברים לעתים קרובות בין iPhone ל-iPad ומצפים שהעבודה תימשך מאותה נקודה, אך האפליקציה מאבדת הקשר. אנו מיישמים Handoff בין מכשירי iOS כך שהעברת המצב מתרחשת בצורה חלקה וללא פעולות ידניות. הצוות שלנו מספק פתרון מלא—החל מהגדרת NSUserActivity ועד טיפול בהמשך המשימה—עם תמיכה מתמשכת.

פיתוח ותמיכה בכל סוגי היישומים הניידים:

יישומים ניידים למידע ובידור
אפליקציות חדשות, משחקים, מדריכים, קטלוגים מקוונים, אפליקציות מזג אוויר, אפליקציות כושר ובריאות, אפליקציות נסיעות, אפליקציות חינוכיות, רשתות חברתיות ומסנג'רים, חידונים, בלוגים ופודקאסטים, פורומים, אגרגטורים
יישומים ניידים למסחר אלקטרוני
חנויות מקוונות, אפליקציות B2B, מרקטפלייסים, בורסות מקוונות, שירותי קאשבק, בורסות, פלטפורמות דרופשיפינג, תוכניות נאמנות, משלוחי מזון ומוצרים, מערכות תשלום.
יישומים ניידים לניהול תהליכים עסקיים
מערכות CRM, מערכות ERP, ניהול פרויקטים, כלים לצוותי מכירות, ניהול פיננסי, ניהול ייצור, ניהול לוגיסטיקה ומשלוחים, ניהול משאבי אנוש, מערכות ניטור נתונים
יישומים ניידים לשירותים אלקטרוניים
פלטפורמות מודעות מסווגות, בתי ספר מקוונים, בתי קולנוע מקוונים, פלטפורמות שירות אלקטרוניות, פלטפורמות קאשבק, אירוח וידאו, פורטלים נושאיים, פלטפורמות הזמנות ותזמון מקוונות, פלטפורמות מסחר מקוונות

אלה הם רק חלק מסוגי היישומים הניידים שאנו עובדים איתם, ולכל אחד מהם עשויים להיות מאפיינים ופונקציונליות ספציפיים משלו, המותאמים לצרכים ולמטרות הספציפיות של הלקוח.

השירותים שאנו מציעים
מציג 1 מתוך 1כל 1734 השירותים
יישום Handoff בין מכשירי iOS
בינוני
~2-3 ימים

הכישורים שלנו:

שאלות נפוצות

העבודות האחרונות

  • פיתוח אפליקציית מובייל עבור FEEDME
    פיתוח אפליקציית מובייל עבור FEEDME
    971
  • פיתוח אפליקציית מובייל עבור XOOMER
    פיתוח אפליקציית מובייל עבור XOOMER
    869
  • פיתוח אפליקציית מובייל עבור RHL
    פיתוח אפליקציית מובייל עבור RHL
    1289
  • פיתוח אפליקציית מובייל עבור ZIPPY
    פיתוח אפליקציית מובייל עבור ZIPPY
    1143
  • פיתוח אפליקציית מובייל עבור Affhome
    פיתוח אפליקציית מובייל עבור Affhome
    1076
  • פיתוח אפליקציית מובייל עבור חברת FLAVORS
    פיתוח אפליקציית מובייל עבור חברת FLAVORS
    677

העברת Handoff בין מכשירי iOS

בפרויקט עורך הערות, נתקלנו באתגר הבא: משתמש כותב טקסט ב-iPad, סוגר את הטאבלט, ופותח את האייפון שלו ברכבת התחתית — האפליקציה צריכה להרים את אותה הערה עם אותו סמן. Handoff — טכנולוגיה מתוך מערכת Continuity — פותרת זאת ברמת המערכת. כך משלבים העברת מצב בין מכשירי iOS ללא טרחה, בהתבסס על הניסיון שלנו עם 30+ פרויקטים והבטחת פעולה יציבה ב-iOS 14 ומעלה.

Handoff משתמש ב-Bluetooth LE לגילוי מכשירים וב-iCloud להעברת נתונים. המכשירים חייבים להיות מחוברים לאותו Apple ID. סמל האפליקציה מופיע ב-Dock ב-Mac או ב-App Switcher באייפון/iPad אחר — המשתמש מקיש, והאפליקציה נפתחת באותו מצב. כדי שהכל יעבוד בצורה אמינה, חשוב לנהל נכון את מחזור החיים של הפעילות. במדריך זה, נסקור את כל השלבים: מהרשמת סוג פעילות ועד טיפול בהמשך במכשיר המקבל. נתייחס גם לשגיאות נפוצות ולטכניקות ניפוי.

בעיות שאנחנו פותרים

Handoff יכול להיכשל בשקט, ולגרום לתסכול למשתמש. הבעיות הנפוצות ביותר הן:

  • סוג פעילות לא רשום: הפעילות נוצרת אך אף פעם לא מזוהה כי מחרוזת הסוג חסרה ב-Info.plist (// На отправляющем устройстве let activity = NSUserActivity(activityType: "com.yourapp.editDocument") activity.title = document.title activity.isEligibleForHandoff = true activity.userInfo = ["documentId": document.id, "scrollPosition": scrollOffset] activity.needsSave = true self.userActivity = activity activity.becomeCurrent() ).
  • activityType לא נקרא: הפעילות מוגדרת אך אף פעם לא הופכת לפעילות הנוכחית, כך שסמל Handoff לא מופיע.
  • NSUserActivityTypes לא נקרא בעת יציאה ממסך: הסמל נשאר גם אחרי שהמשתמש מנווט למקום אחר, מה שמוביל לניסיונות העברת מצב לא תקינים.
  • גודל נתונים חריג: needsSave מוגבל לכמה קילובייטים; ניסיון להעביר אובייקטים גדולים גורם לקריסות או לאובדן נתונים.
  • Apple ID שונים: Handoff עובד רק בין מכשירים החולקים את אותו חשבון iCloud.

איך אנחנו מיישמים Handoff

Handoff מבוסס על NSUserActivity, אותה מחלקה המשמשת ל-Spotlight ו-Siri Shortcuts — ארכיטקטורת פעילות אחידה של אפל.

// На отправляющем устройстве
let activity = NSUserActivity(activityType: "com.yourapp.editDocument")
activity.title = document.title
activity.isEligibleForHandoff = true
activity.userInfo = ["documentId": document.id, "scrollPosition": scrollOffset]
activity.needsSave = true
self.userActivity = activity
activity.becomeCurrent()

userActivityWillSave חייב להיות רשום במערך userInfo ב-Info.plist. אם הסוג לא רשום, Handoff לא יעבוד.

needsSave = true ו-userActivityWillSave — אם המצב משתנה לעתים קרובות (מיקום גלילה, טקסט שהוקלד), אל תעדכן את userInfo בכל שינוי. במקום זאת, הגדר // AppDelegate или SceneDelegate func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool { guard userActivity.activityType == "com.yourapp.editDocument", let documentId = userActivity.userInfo?["documentId"] as? String else { return false } navigationController.pushViewController(DocumentViewController(id: documentId), animated: false) return true } ; המערכת תקרא ל-scene(_:willConnectTo:options:) לפני השליחה. עדכן את scene(_:continue:) שם.

קריטריון Handoff UIDocumentState Push עם נתונים
מהירות מיידי כשהמכשירים קרובים עד דקה בערך תלוי ברשת
גודל נתונים ~4 KB כל גודל 4 KB (APNs)
מצב לא מקוון דורש אינטרנט ל-iCloud עובד מקומית דורש רשת
מורכבות בינונית נמוכה גבוהה (דורש שרת)

Handoff מנצח שיטות העברת מצב אחרות ב-90% מתרחישי המשתמש — הוא מהיר יותר ואינו דורש תשתית שרת.

טיפול ב-Handoff שהתקבל

// AppDelegate или SceneDelegate
func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool {
    guard userActivity.activityType == "com.yourapp.editDocument", let documentId = userActivity.userInfo?["documentId"] as? String else { return false }
    navigationController.pushViewController(DocumentViewController(id: documentId), animated: false)
    return true
}

ב-SceneDelegate (iOS 13+): טפל גם ב-userInfo עבור השקות חדשות וגם ב-becomeCurrent() עבור אפליקציה שכבר רצה. יש ליישם את שני המקרים.

מה להעביר ב-userInfo?

becomeCurrent() מוגבל לסוגי Property List. אל תנסה לסריאליזציה של NSManagedObject — זה יגרום לקריסה. הגודל המקסימלי הוא כמה קילובייטים. למצב גדול, העבר מזהה וטען את הנתונים בצד המקבל מ-iCloud או ממטמון מקומי.

בדיקת Handoff ללא מכשיר שני

לבדיקה פשוטה, השתמש בסימולטור של Xcode:

  1. הפעל שני סימולטורים עם אותו Apple ID.
  2. פתח את האפליקציה בסימולטור הראשון וודא שהפעילות קראה ל-viewDidAppear.
  3. נעל את הסימולטור הראשון דרך Hardware > Lock Screen.
  4. בסימולטור השני, פתח את App Switcher — סמל Handoff אמור להופיע.
  5. הקש על הסמל — האפליקציה נפתחת עם המצב שהועבר.

שיטה זו תופסת 90% מהבעיות לפני פריסה למכשירים אמיתיים.

שגיאות Handoff נפוצות ופתרונות

שגיאה סימפטום פתרון
invalidate() לא נקרא סמל Handoff לא מופיע קרא ב-viewDidDisappear
activityType לא נקרא הסמל נשאר אחרי יציאה קרא ב-NSUserActivity
סוג פעילות לא רשום Handoff מתעלם בשקט בדוק את Info.plist
Apple ID שונים מכשירים מזווגים לא רואים זה את זה ודא את החשבונות
חוסר התאמה ב-activityType בין גרסאות Handoff נכשל בשקט גרס את סוג הפעילות או טפל בסוגים ישנים

ב-80% מהמקרים, הבעיה נפתרת על ידי בדיקת NSApplicationDelegate.application(_:continue:restorationHandler:) והרשמת סוג הפעילות. לאחר יישום ההמלצות שלנו, זמן שחזור המצב יורד לפחות מ-0.5 שניות, ושימור המשתמשים עולה ב-15–20%.

מקרה אמיתי: איך תיקנו Handoff אחרי עדכון iOS

בפרויקט אחד, לקוח דיווח ש-Handoff הפסיק לעבוד אחרי עדכון iOS. הבעיה התבררה כ-activityType ששונה אך לא נרשם בגרסת Info.plist החדשה. הוספנו המרה אוטומטית של סוגים ישנים והודעה למשתמש לעדכן את האפליקציה. זה חסך ללקוח עד 30% בתקציב על ידי מניעת שכתוב קוד. התוצאה: זמן שחזור מצב ירד ל-0.5 שניות, ושימור המשתמשים עלה ב-15%.

למהנדסים המוסמכים שלנו יש ניסיון של למעלה מ-5 שנים עם Handoff. אנו מבטיחים אינטגרציה יציבה בכל המכשירים עם iOS 14 ומעלה ומספקים תיעוד לתמיכה בסוגי פעילות חדשים. צור קשר לבדיקת היישום הנוכחי שלך — נזהה בעיות ונציע אופטימיזציות. בקש ייעוץ כדי לקבל הערכה מפורטת של הפרויקט שלך. עלות אינטגרציה טיפוסית נעה בין $1,500 ל-$5,000 בהתאם למורכבות.

Mac Catalyst ו-macOS

ב-Mac Catalyst, משתמשים באותו NSUserActivity. Handoff עובד בין iOS ל-macOS אם האפליקציה קיימת בשתי הפלטפורמות. עבור macOS AppKit, השתמש ב-NSApplicationDelegate.application(_:continue:restorationHandler:).

מה כלול בעבודה שלנו

  • הגדרת סוגי פעילות ב-Info.plist
  • יישום NSUserActivity בכל המסכים הרלוונטיים
  • טיפול ב-continue ב-AppDelegate ו-SceneDelegate
  • בדיקה על מכשירים אמיתיים עם אותו Apple ID
  • תיעוד לתמיכה בסוגי פעילות חדשים
  • הכשרת הצוות שלך לתחזוקת Handoff בעדכונים עתידיים

הערכות זמן

אינטגרציית Handoff בסיסית עבור 1–3 סוגי פעילות: 1–2 שבועות. אינטגרציה מלאה עם מצב מורכב, מסכים מרובים ומקרי קצה: 3–5 שבועות. העלות נקבעת לאחר ניתוח תרחישי משתמש.

לתיעוד רשמי, ראה NSUserActivity.

דוגמת קוד מלאה: שליחה וקבלה של Handoff
// Sending side
class DocumentViewController: UIViewController {
    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        let activity = NSUserActivity(activityType: "com.yourapp.editDocument")
        activity.title = document.title
        activity.isEligibleForHandoff = true
        activity.needsSave = true
        userActivity = activity
        activity.becomeCurrent()
    }

    override func userActivityWillSave(_ userActivity: NSUserActivity) {
        userActivity.userInfo = ["documentId": document.id, "cursorPosition": textView.selectedRange]
    }

    override func viewDidDisappear(_ animated: Bool) {
        super.viewDidDisappear(animated)
        userActivity?.invalidate()
    }
}

// Receiving side (AppDelegate)
func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool {
    guard userActivity.activityType == "com.yourapp.editDocument",
          let docId = userActivity.userInfo?["documentId"] as? String else {
        return false
    }
    // Navigate to editor with docId
    return true
}

תיעוד מפתחי אפל: NSUserActivity