Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

iOS app launch due to NSUserActivity. How do access that object?

Tags:

So testing some ios9 beta features as of now, but NSUserActivity class has been out for a while, which is used in handoff.

Basically this is it. When app launches doe to NSUserActivity, I can see that this the launchOptions has a key set.

    NSDictionary *userActivityKey = [launchOptions objectForKey:UIApplicationLaunchOptionsUserActivityDictionaryKey]; 

Basically the method never gets called.

- (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void(^)(NSArray * __nullable restorableObjects))restorationHandler 

This makes sense as the app is just being opened due to the activity. But what is puzzling me is this.

When I check the launchOptions, I am not able access the NSUserActivity. Apparently the OS creates that object for you??

Did any of you guys deal with this?

like image 321
Legolas Avatar asked Aug 24 '15 21:08

Legolas


People also ask

What is foreground state in iOS?

Overview. Use foreground transitions to prepare your app's UI to appear onscreen. An app's transition to the foreground is usually in response to a user action. For example, when the user taps the app's icon, the system launches the app and brings it to the foreground.

Which are the app's state transitions when it is launched?

After launch, the system puts the app in the inactive or background state, depending on whether the UI is about to appear onscreen. When launching to the foreground, the system transitions the app to the active state automatically. After that, the state fluctuates between active and background until the app terminates.

What is NSUserActivity in Swift?

An NSUserActivity object provides a lightweight way to capture the state of your app and put it to use later. Create this object to capture information about what a person was doing, such as viewing app content, editing a document, viewing a web page, or watching a video.


2 Answers

You shouldn't be doing any of that. You should return YES from -(BOOL)application:didFinishLaunchingWithOptions:, then -(BOOL)application:continueUserActivity:restorationHandler will also be called. Apple docs say:

NO if the app cannot handle the URL resource or continue a user activity, otherwise return YES.

like image 75
ernesto Avatar answered Sep 19 '22 15:09

ernesto


I used a UIAlertView to get a description of the launchOptions when coming from an NSUserActivity:

NSDictionary *userActivityDictionary = [launchOptions objectForKey:UIApplicationLaunchOptionsUserActivityDictionaryKey]; UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"alert"                                                     message:[userActivityDictionary description]                                                    delegate:nil                                           cancelButtonTitle:@"Okay"                                           otherButtonTitles:nil]; [alertView show]; 

Apparently, this dictionary comes with a couple keys that I cannot seem to find documentation for:

UIApplicationLaunchOptionsUserActivityIdentifierKey UIApplicationLaunchOptionsUserActivityKey UIApplicationLaunchOptionsUserActivityTypeKey // there is documentation for this key 

enter image description here

It seems the NSUserActivity object is inside this dictionary, but it may not be good from Apple's point of view (or it may break if Apple decides to change things), to try to access this object (e.g., possibly looping through the dictionary keys and looking for an NSUserActivity object).

**** Solution ****

EDIT: Here's some implementation on how to access the NSUserActivity object from launchOptions:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {     NSDictionary *userActivityDictionary = [launchOptions objectForKey:UIApplicationLaunchOptionsUserActivityDictionaryKey];     if (userActivityDictionary) {         [userActivityDictionary enumerateKeysAndObjectsUsingBlock:^(id  _Nonnull key, id  _Nonnull obj, BOOL * _Nonnull stop) {                 if ([obj isKindOfClass:[NSUserActivity class]]) {                     NSLog(@"found NSUserActivity object!");                 }             }];     } } 

Using this method, you don't need to know the value of the undocumented key, UIApplicationLaunchOptionsUserActivityKey.

If you're uncomfortable with the solution above, another method may be to catch the NSUserActivity object when your app enters this method,

- (BOOL)application:continueUserActivity:restorationHandler: 

Then, set this user activity as a property of your AppDelegate for later retrieval.

Note: I was able to verify that the method above is called on a cold app launch while testing Core Spotlight (iOS 9 feature).

like image 44
markckim Avatar answered Sep 19 '22 15:09

markckim