About Handoff
Handoff is a capability introduced in iOS 8 and OS X v10.10 that transfers user activities among multiple devices associated with the same user. In iOS 9 and OS X v10.11, Handoff helps your app participate in search by making it possible to designate user activities and app states as searchable. For example, when a searchable activity or state appears in Spotlight search results or Siri suggestions, users can tap the result to return to the relevant area in your app.
Handoff lets users switch from one device to another and continue an ongoing activity seamlessly, without reconfiguring each device independently. For example, a user who is browsing a long article in Safari on a Mac can move to a nearby iOS device that’s signed into iCloud with the same Apple ID and open the same webpage automatically in Safari on iOS, at the same scroll position as on the original device.
Apple apps, such as Safari, Mail, Maps, Contacts, Notes, Calendar, and Reminders use public APIs to implement Handoff for iOS 8 and OS X v10.10. A third-party developer can use the same APIs to implement Handoff in apps that share the developer’s Team ID. Such apps must either be distributed through the App Store or signed by the registered developer.
Handoff Interactions
Handing off a user activity involves three phases:
Create a user activity object for each activity the user engages in your app.
Update the user activity object regularly with information about what the user is doing.
Continue the user activity on a different device when the user requests it.
Document-based apps (that is, apps based on a subclass of NSDocument
or UIDocument
), provide built-in support for all three phases of the handoff scenario. Responder objects (subclasses of NSResponder
and UIResponder
) provide built-in support for updating user activities and managing their current status. Your app can also create, update, and continue user activities directly, working especially with the app delegate.
The Handoff mechanism depends primarily on objects of a single class in Foundation, NSUserActivity
, with support of additional small APIs in UIKit and AppKit. Apps encapsulate information about a user’s activities in NSUserActivity
objects, and those activities become candidates for continuation on other devices. Handoff of a given user activity requires the originating app to designate that activity’s NSUserActivity
object as the current activity, save pertinent data for continuation on another device, and send the data to the resuming device. Handoff passes only enough information between the devices to describe the activity itself, while larger-scale data synchronization is handled through iCloud.
On the continuing device, the user is notified that an activity is available for continuation. If the user chooses to continue the activity, an appropriate app is launched and provided with the activity’s payload data. A user activity can be continued only in an app that has the same developer Team ID as the activity's source app and that supports the activity's type. Supported activity types are specified in the app's Info.plist
under the NSUserActivityTypes
key (for more information about this key, see NSUserActivityTypes). So, the continuing device chooses the appropriate app based on the target Team ID, activity type property of the originating NSUserActivity
object, and optionally the activity object’s title property. From the information in the user activity object’s userInfo
dictionary, the continuing app can then configure its user interface and state appropriately for seamless continuation of the user’s activity.
Optionally, if continuing an activity requires more data than can be efficiently transferred by the initial transport mechanism, a resuming app can call back to the originating app’s activity object to open streams between the apps and transfer more data. For example, if the activity to be continued is composing an email message that contains an image, then the streams option is the best way to transfer the data needed to continue the composition on another device. For more information, see Using Continuation Streams.
Document-based apps on iOS and OS X automatically support Handoff, as described in Supporting a User Activity in Document-Based Apps.
User Activity Object
An NSUserActivity
object encapsulates the state of a user activity in an app on a particular device. It is the primary object in the Handoff mechanism and it helps you designate an activity or app state as searchable. The originating app creates a user activity object for each user activity that can be handed off to another device or that can appear in Spotlight search results. For example, a web browser would create a user activity object for each open tab or window in which the user is browsing URLs. However, only the activity object corresponding to the frontmost tab or window is current at a given time, and only the current activity is available for continuation.
An NSUserActivity
object is identified by its activityType
and title
properties. In addition, you can use properties such as keywords
and contentAttributeSet
to provide rich information about an activity to display in search results.
The NSUserActivity
class defines properties you use to specify the eligibility of an activity for various uses. For example, you can use eligibleForSearch
to add an activity to the on-device index and enable it to show up in the user’s search results and you can use expirationDate
to specify a date after which an activity is no longer eligible to be indexed or handed off.
An NSUserActivity
object also has a userInfo
dictionary to contain its state data and a flag named needsSave
that supports lazy updating of its state by its delegate. The NSUserActivity
method addUserInfoEntriesFromDictionary:
enables the delegate and other clients to merge state data into its userInfo
dictionary.
For more information, see NSUserActivity Class Reference.
User Activity Delegate
The user activity delegate is an object that conforms to the NSUserActivityDelegate
protocol. It is typically a top-level object in the app, such as a view controller or the app delegate, that manages the activity’s interaction with the app.
The user activity delegate is represented by the delegate
property of NSUserActivity
and is responsible for keeping the data in the NSUserActivity
object’s user info dictionary up to date so that it can be handed off to another device. When the system needs the activity to be updated, such as before the activity is continued on another device, it calls the delegate’s userActivityWillSave:
method. You can implement this callback to make updates to the object’s data-bearing properties such as userInfo
, title
, and so on. Once the system calls this method, it resets needsSave
to NO
. Change this value to YES
if something happens that changes the userInfo
or other data-bearing properties again.
Alternatively, instead of implementing the delegate’s userActivityWillSave:
method, you can have UIKit or AppKit manage the user activity automatically. The app opts into this behavior by setting a responder object’s userActivity
property and implementing the responder’s updateUserActivityState:
callback, as described in Managing a User Activity With Responders. This arrangement is preferred if it works for your user activity.
For more information, see NSUserActivityDelegate Protocol Reference.
App Framework Support
UIKit and AppKit provide support for Handoff in the document, responder, and app delegate classes. Although there are minor behavioral differences between the platforms, the basic mechanism, which enables apps to save and restore user activities, is the same, and the APIs are the same.
Supporting a User Activity in Document-Based Apps
A document-based app on iOS and OS X automatically supports Handoff if you add an NSUbiquitousDocumentUserActivityType
key and value for each CFBundleDocumentTypes
entry in your app’s Info.plist
property list file. If this key is present, NSDocument
and UIDocument
automatically create NSUserActivity
objects for iCloud-based documents of the given document type. The value of NSUbiquitousDocumentUserActivityType
is a string that represents the NSUserActivity
object’s activity type. That is, you provide an activity type for each document type supported by your document-based app. Multiple document types can have the same activity type. NSDocument
and UIDocument
automatically put the value of their fileURL
property into the activity object’s userInfo
dictionary with the NSUserActivityDocumentURLKey
.
In OS X, AppKit can automatically restore NSUserActivity
objects created in this way. It does so if the app delegate method application:continueUserActivity:restorationHandler:
returns NO
or is unimplemented. In this situation, the document is opened with the NSDocumentController
method openDocumentWithContentsOfURL:display:completionHandler:
and receives a restoreUserActivityState:
message.
For more information, see Adopting Handoff in Document-Based Apps. Also see NSDocument Class Reference and UIDocument Class Reference.
Managing a User Activity with Responders
UIKit and AppKit can manage a user activity if you set it as a responder object’s userActivity
property. When the responder knows that the activity state is dirty, it must set the object’s needsSave
property to YES
. The system automatically saves the NSUserActivity
object at appropriate times, first giving the responder an opportunity to update the activity’s state through the updateUserActivityState:
callback. Your responder subclass must override the updateUserActivityState:
method to add state data to the user activity object. If multiple responders share a single NSUserActivity
object, they all receive an updateUserActivityState:
callback when the system updates the user activity object. Before the update callbacks are sent, the activity object’s userInfo
dictionary is cleared.
In OS X, NSUserActivity
objects managed by AppKit and associated with responders automatically become current based on the main window and the responder chain, that is, when the document’s window becomes the main window. In iOS, however, for NSUserActivity
objects managed by UIKit, you must either call becomeCurrent
explicitly or have the document’s NSUserActivity
object set on a UIViewController
object that is in the view hierarchy when the app comes to the foreground.
A responder can set its userActivity
property to nil
to disassociate itself from an activity. When an NSUserActivity
object managed by the app framework has no more associated responders or documents, it is automatically invalidated.
For more information, see Adopting Handoff in Responders. Also see NSResponder Class Reference or UIResponder Class Reference.
Continuing an Activity Using the App Delegate
The app delegate is the primary entry point for continuing a user activity in a non-document-based app. As soon as the user chooses to resume an activity, either by responding to the notification or by selecting a search result, Handoff launches the appropriate app and sends the app’s delegate an application:willContinueUserActivityWithType:
message. The app lets the user know that the activity will continue shortly. Meanwhile, the NSUserActivity
object is delivered when the delegate receives an application:continueUserActivity:restorationHandler:
message. You should implement this method to configure your app in such a way that it can resume the activity represented by the user activity object.
The application:continueUserActivity:restorationHandler:
message includes a block, the restoration handler, that you can optionally call if your app uses auxiliary responder or document objects to perform the resuming user activity. Create these objects (or fetch them if cached) and pass them to the restoration handler in its NSArray
parameter. The system then sends each object a restoreUserActivityState:
message, passing the user activity object. Each object can use the activity’s userInfo
data to resume the activity. For more information about using this restoration handler, see the description of the application:continueUserActivity:restorationHandler:
method in NSApplicationDelegate Protocol Reference.
When you continue an activity that was chosen in a search result, you should regenerate the keywords for the activity, if appropriate, because the activity you receive may not have the same properties as the activity that was originally created.
If you do not implement application:continueUserActivity:restorationHandler:
or return NO
from it, and your app is document-based, AppKit can automatically resume the activity, as described in Supporting User Activity in Document-Based Apps. For more details, see Continuing an Activity.
Copyright © 2016 Apple Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2016-04-01