Handoff簡介 Handoff是iOS 8 和 OS X v10.10中引入的功能,可以讓同一個用戶在多台設備間傳遞項目。In iOS 9 and OS X v10.11 支持了Spotlight中搜索並打開應用。 Handoff交互: 在iOS中這個user activity object是U ...
Handoff簡介
Handoff是iOS 8 和 OS X v10.10中引入的功能,可以讓同一個用戶在多台設備間傳遞項目。In iOS 9 and OS X v10.11 支持了Spotlight中搜索並打開應用。
Handoff交互:
- 在你的app中為每一個活動創建一個user activity 對象
- 定期使用用戶的信息更新user activity對象
- 當用戶請求時在不同的設備上繼續用戶活動
在iOS中這個user activity object是UIKit中的 NSUserActivity類。
Handoff需要的硬性條件:
-
互通的所有設備必須支持 Buletooth LE 4.0,Handoff使用BLE信號來傳遞用戶活動數據。
-
所有設備必須連到同一個iCloud賬戶。
-
當然你還得保證當前設備的Handoff功能打開了(iOS:設置->通用->Handoff 與建議的應用程式。 Mac:系統偏好設置->通用,倒數第二欄有個選項,"允許這台Mac和iCloud設備之間使用Handoff")
BLE並不像傳統的藍牙,並不需要人工手動進行配對,只要打開就行了,所有的配對數據傳輸都是自動完成的;設備並不一定需要連在同一個WIFI網路中,Handoff的活動基礎數據通過BLE進行傳遞,較大的數據通過iCloud同步(通過網路streams,比如郵件中有個圖片)。
工作流程
Handoff編程的核心類便是NSUserActivity了,代表著一個用戶的活動,每一個Activity都有一個activityType,用來標識Activity的類型。當App間進行Handoff的話,需要滿足下麵幾個條件:
- 在iCloud 中使用相同的 Apple ID登錄
-
和發佈Activity的App擁有相同的TeamID
-
在應用中你想要支持的Target的Info.plist文件中加入活動標識NSUserActivityTypes
第三方開發的app必須通過App Store發佈或者使用註冊開發者簽名。啟動了Handoff功能的app,在使用期間Handoff消息會通過BLE進行分發,iOS設備接收到消息後會檢查與起始app是否具有相同TeamID以及相同NSUserActivityTypes,如果找到了則在“另一部”設備中顯示推薦app。
User Activity 對象
NSUserActivity對象存儲用戶的活動信息,實現在不同設備上的繼續工作。起始app必須顯式調用becomeCurrent或者基於文件的app(Document-based apps)進入前臺時,給在視圖層級中的UIViewController對象設置文件的NSUserActivity對象來啟用Handoff功能。將其設置resignCurrent或者Document-based app的NSUserActivity對象設置為nil停用。
NSUserActivity對象的唯一標示是 activityType
and title
屬性(document name or web page title)。通過eligibleForSearch、 keywords
and contentAttributeSet
屬性的支持,可以使其app支持Spotlight搜索結果中顯示。通過 expirationDate設置失效時間。
NSUserActivity對象通過userInfo
dictionary 屬性來存儲並共用數據信息。
User Activity 同步機制
User Activity的同步機制分兩種:延時更新(lazy updating )和系統管理。
- lazy updating
- 需要同步的用戶數據有更新時,將User Activity對象的
needsSave屬性設置為YES
NSUserActivity
將要共用數據之前,會調用起始app的userActivityWillSave:
方法(NSUserActivityDelegate),在此方法中通過NSUserActivity
methodaddUserInfoEntriesFromDictionary:
方法merge相關狀態信息到userInfo
對象中。調用完此方法,系統會將needsSave屬性重置為NO。
- 需要同步的用戶數據有更新時,將User Activity對象的
- 系統管理
- 當響應者知道activity的狀態已修改,它必須設置
needsSave設置為YES
(When the responder knows that the activity state is dirty, it must set the object’sneedsSave
property toYES
. )。系統會在合適的時間自動同步NSUserActivity
對象,首先會通過updateUserActivityState:回調給響應者更新activity’s state的機會。你的響應者子類必須重寫updateUserActivityState:方法來給user activity對象添加狀態數據(在此方法中通過
NSUserActivity
methodaddUserInfoEntriesFromDictionary:
方法merge相關狀態信息到userInfo 對象中
)。如果多個響應者共用一個NSUserActivity對象,當系統更新user activity對象時,它們都會收到updateUserActivityState:回調。在更新回調發送之前,activity對象的userInfo字典會被清空。
- 當響應者知道activity的狀態已修改,它必須設置
使用App Delegate來繼續activity的使用
在非document app中,通過Handoff啟動響應者app的時候,會在app的delegate中收到application:willContinueUserActivityWithType:和application:continueUserActivity:restorationHandler:消息,分四種情況處理:
- 普通模式,正常處理
-
func application(application: UIApplication, continueUserActivity userActivity: NSUserActivity, restorationHandler: ([AnyObject]!) -> Void) -> Bool { self.window?.rootViewController?.restoreUserActivityState(userActivity) return true } override func restoreUserActivityState(activity: NSUserActivity) { self.noteTitleField.text = activity.userInfo?["title"] as! String self.noteContentView.text = activity.userInfo?["content"] as! String }
-
- 如果需要其他響應者或者文件對象來恢復user activity,則需要調用block,數組包括UIResponder集合,然後會讓每個對象收到
restoreUserActivityState:
消息。 - 如果你繼續的activity是通過搜索列表而來,那可以在這裡重新設置keyword。
- 如果沒有實現application:continueUserActivity:restorationHandler:或者返回NO,並且app是基於文件的(document-based),AppKit可以自動恢復用預設的NSUserActivity對象。在這種情況,文件會使用NSDocumentController的方法openDocumentWithContentsOfURL:display:completionHandler: 來打開,並且會收到一條restoreUserActivityState: 消息。
基於文件的app中支持User Activity
基於文件的app如果Info.plist中添加了CFBundleDocumentTypes則預設支持Handoff功能。NSUbiquitousDocumentUserActivityType 對應的字元串作為NSUserActivity對象的activity type。基於iCloud來同步文件,並且自動生成並存儲到fileURL屬性中,如果app delegate方法application:continueUserActivity:restorationHandler:返回NO,或者沒有實現,那麼AppKit可以自動恢復用上面方式創建的NSUserActivity對象。在這種情況,文件會使用NSDocumentController的方法openDocumentWithContentsOfURL:display:completionHandler: 來打開,並且會收到一條restoreUserActivityState: 消息。
總結
Handoff可以實現iOS8之後的設備之間的“連續互動”,基於UIDocument
的文件app(Info.plist實現了CFBundleDocumentTypes)則預設支持Handoff功能。非文件的app需要實現NSUserActivityTypes在Info.plist中,然後可以分為laze和系統管理兩種同步機制。看的一些blog說需要連接同一網路,其實是沒有必要的。可以通過apple自己提供的預設支持app來做測試(Mac 訪問Safari,手機關閉wifi也會有提示)
iphone左下角的提醒應用圖標的機制有三種方式,Handoff只是其中一種,後面我會有單獨介紹著三種的實現及卻別。
參考資料
https://developer.apple.com/library/ios/documentation/UserExperience/Conceptual/Handoff/HandoffFundamentals/HandoffFundamentals.html#//apple_ref/doc/uid/TP40014338-CH3-SW1