I think I have a better solution.
It consists in maintaining a Bool in each page controller that tells whether the controller is active (displayed), and in keeping a value for the NSUserActivity that needs to be updated to the OS
private var isActive:Bool = false {
didSet(oldValue) {
if oldValue != isActive {
resolveHandoff()
}
}
}
private var currentUserActivity: NSUserActivity? {
didSet(oldUserActivity) {
if oldUserActivity == nil && currentUserActivity != nil
|| oldUserActivity != nil && currentUserActivity == nil
|| oldUserActivity != currentUserActivity {
resolveHandoff()
}
}
}
override func willActivate() {
super.willActivate()
self.isActive = true
}
override func didDeactivate() {
super.didDeactivate()
self.isActive = false
}
private func resolveHandoff() {
if !self.isActive {
return
}
if let activity = currentUserActivity {
self.updateUserActivity(activity.activityType, userInfo: activity.userInfo, webpageURL: nil)
} else {
self.invalidateUserActivity()
}
}
Now you can «tag» your user activity wherever you want in the interface controller code by simply assigning a value for currentUserActivity. For instance it can be in the awakeWithContext: method
override func awakeWithContext(context: AnyObject?) {
super.awakeWithContext(context)
let ua = NSUserActivity(activityType: "com.mycompany.doingSomething")
ua.userInfo = ["My key": "My value"]
self.currentUserActivity = ua
}
The user activity will be reported only if currentUserActivity is set and the controller is active (displayed).
Note that the way it is implemented above allows you to invalidateUserActivity by simply setting self.currentUserActivity = nil when your controller is active.