continueUserActivity not called from search closed app
Asked Answered
A

8

31

I am trying to use core spotlight to open a view controller from the spotlight search results.

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

if(self.window.rootViewController){
    [self.window.rootViewController restoreUserActivityState:userActivity];
}

return YES;
}

This seems to work when the app is already running in background, however when it is closed and I tap on the spotlight search result it seems that this method gets not called and the behavior I get is that my application simply starts in the main interface.

Do you have any suggestion for making it work also when my app is closed? Is there a way to debug what is happening (since I need to run the app to get the debugger attached I don't know how to simulate the app opening from the search result)?.

Anana answered 20/9, 2015 at 10:0 Comment(2)
Did you ever figure this out? I'm having the same issue: continueUserActivity is ever being called.Misshape
Hi @Travis, see my answer below :)Anana
A
4

Here it follows the complete answer following your advices.

// In application: didFinishLaunchingWithOptions:
NSDictionary *activityDic = [launchOptions objectForKey:UIApplicationLaunchOptionsUserActivityDictionaryKey];

if (activityDic) {
    if(self.window.rootViewController){
        NSUserActivity * userActivity = [activityDic valueForKey:@"UIApplicationLaunchOptionsUserActivityKey"];
        [self.window.rootViewController restoreUserActivityState:userActivity];
    }
}
Anana answered 17/10, 2015 at 10:32 Comment(1)
you should really explain what you have got hereEducation
A
55

Niko,

first of all: there's a way to start your app from Xcode and not opening it immediately: open your scheme properties, go to the "run" section, and under "info", there's a switch that will help you to debug what's happening:

"Wait for executable to be launched".

If you activate this switch, you can launch the app from Xcode, Xcode will wait until the app is opened from search and then it will attach the debugger to it.

Hope that helps!

Ivan

Astrodome answered 21/9, 2015 at 15:33 Comment(0)
R
44

In the new Swift 5 there is a new new file called SceneDelegate.swift. Use the method scene(_ scene: UIScene, continue userActivity: NSUserActivity)

Radley answered 4/10, 2019 at 14:6 Comment(3)
Wasted 2 hours on this, stupid outdated documentation.Embolic
How to get url from user activity if app is still supporting iOS 9 ... ?Brendonbrenk
can i buy you a beer!?Sanity
S
23

If you are using the Facebook SDK, and in didfinishlaunching your are returning FBSDK, instead of plain text, and returning true at the end, it can cause problems hitting continueuseractivity.

After searching a lot, and trying different ways, I just had to return true and comment this:

FBSDKApplicationDelegate.sharedInstance().application(application, didFinishLaunchingWithOptions: launchOptions)

Surrejoinder answered 18/11, 2015 at 23:49 Comment(4)
this is an unexpected correct solution for me, after hitting my head to the wall for several hours. upvoted.Musjid
Dude, great catch. This saved me.Jesicajeske
Wow, this was unexpected. Damn you Facebook! Great catch indeed!Saintsimonianism
This is unexpectedly valid even today. Thank you for this.Inversely
S
12

continue userActivity is changed in the latest swift version. Changing the func worked for me.

func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([Any]?) -> Void) -> Bool

to

func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool.
Standing answered 22/7, 2019 at 10:21 Comment(5)
This is awesome!!Nies
Thx!!!! This saved my lifeDeclan
is this still valid in 2022?Education
This should be the accepted answer, works as of 2022-JULStreptokinase
This method is called only when the app is available in the device, what if the app is not in the phone and you installing the app in by clicking the universal link. will this method redirection function is works for you?Buchbinder
A
11

If your app uses Scenes, make sure you have implemented both delegates:

this one for the case when the app is not running at the moment of clicking the link:

   func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
      // the url is expected to be in connectionOptions.userActivities.first?.webpageURL in case if its type is NSUserActivityTypeBrowsingWeb
   }

AND this one for the case when the app is in background or in foreground:

   func scene(_ scene: UIScene, continue userActivity: NSUserActivity) {
       // the url is going to be in userActivity.webpageURL
   }

If your app does NOT use Scenes:

Double-check this method call carefully, because it has changed some time ago and legacy projects can still have old code:

func application(_ application: UIApplication, 
                   continue userActivity: NSUserActivity, 
                   restorationHandler: @escaping ([Any]?) -> Void) -> Bool

This is the call which worked in my case:

func application(_ application: UIApplication, 
                   continue userActivity: NSUserActivity, 
                   restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool

(Don't be deceived by Xcode's warning suggesting to add private - it won't help)

Check Apple's documentation about Universal Links for more details.

Additional answered 14/2, 2019 at 12:49 Comment(1)
This should be ranked higher: it's the correct answer in 2022.Suffolk
L
10

didFinishLaunchingWithOptions needs to return YES so continueUserActivity will be called.

Add to End of application: didFinishLaunchingWithOptions:

NSDictionary *activityDictionary = launchOptions[UIApplicationLaunchOptionsUserActivityDictionaryKey];
if (activityDictionary) {
    NSUserActivity *userActivity = activityDictionary[UIApplicationLaunchOptionsUserActivityTypeKey];
    if (userActivity) {
        return YES;
    }
}

return NO;
Loy answered 8/2, 2016 at 22:4 Comment(2)
willFinishLaunchingWithOptions also needs to return YESLyly
thx @Lyly I lost lot of time before to find your comment, and willFinishLaunchingWithOptions was required to return YES for me too!Octahedron
P
8

If the app was closed, application: continueUserActivity: is not called. Instead, you get all the information launchOptions dictionnary in application: didFinishLaunchingWithOptions:

// In application: didFinishLaunchingWithOptions:
NSDictionary *activityDic = [launchOptions objectForKey:UIApplicationLaunchOptionsUserActivityDictionaryKey];  
if (activityDic) {
    // Continue activity here
}
Pellegrino answered 7/10, 2015 at 14:36 Comment(0)
A
4

Here it follows the complete answer following your advices.

// In application: didFinishLaunchingWithOptions:
NSDictionary *activityDic = [launchOptions objectForKey:UIApplicationLaunchOptionsUserActivityDictionaryKey];

if (activityDic) {
    if(self.window.rootViewController){
        NSUserActivity * userActivity = [activityDic valueForKey:@"UIApplicationLaunchOptionsUserActivityKey"];
        [self.window.rootViewController restoreUserActivityState:userActivity];
    }
}
Anana answered 17/10, 2015 at 10:32 Comment(1)
you should really explain what you have got hereEducation

© 2022 - 2024 — McMap. All rights reserved.