NSUserActivity results

In my viewController, I'm creating an NSUserActivity, attaching an CSSearchableItemAttributesSet, assigning the activity to the viewController's userActivity property, and then calling becomeCurrent on the activity as below:


NSUserActivity *userActivity = [[NSUserActivity alloc] initWithActivityType:activity.uniqueIdentifier];
CSSearchableItemAttributeSet *attribs = [self attributesForActivity:activity]; //sets title, contentDescription
userActivity.contentAttributeSet = attribs;
userActivity.eligibleForSearch = YES;
userActivity.eligibleForHandoff = YES;
userActivity.eligibleForPublicIndexing = YES;
self.userActivity = userActivity;
[self.userActivity becomeCurrent];


But nothing is showing up. I've tried running this on the simulator and on an iPhone 5 device, but nothing is happening. Can't see any log files to indicate anything is amiss.


If I use Core Spotlight and add the same item to the index, it shows up immediately on both device and simulator. Is the NSUserActivity integration not working yet?

NSUserActivity does not work on the simulator (either for handoff or for search). This was confirmed to me by an engineer at WWDC 15's "Search API" lab.

What build are you running? Please file a bug report and if you can include a sample project that would be great.

Do you have it working on a device? I can't get it working on a device or the simulator.

Running beta2. (It didn't work on beta1 either)


I'm happy to file a bug report, but I'm only trying the simplest of cases (the code I posted above) and it's not working, which is why I'm asking here first. I'm doing nothing compliated. The code I posted above is basically the whole thing. Wondering if there's some other step I need to take to get the activity to be indexed?


I also tried setting `self.userActivity.needsSave = YES;` for good measure

Yes, please file a bug report. From the looks of the code you pasted above that should be fine (assuming self.userActivity is a strong reference, is it?).

Similarly, please file a bug report with details of what you're doing. What device are you trying to run on?

Creating a test project now.


self.userActivity is the property on UIResponder. (Which the docs list as Strong) - I also tried it with my own strong property which doesn't seem to make any difference.

Filed as 21561771

Terrific, thank you very much! You should not have to set needsSave = YES on the activity. Just making it current should be enough. We're looking at the issues being reported with Seed 2.

FWIW this seems to be working fine in beta 3 on the simulator.

I am having the same problem. Doesn't work on beta 4 either. Does anybody have any ideas how to debug the problem? Has somebody gotten it to work?

I haven't tried on b4. It worked for me on b3 on a device (not iPad2 or iPad mini) and make sure you don't set a relatedUniqueIdentifier if you want it to actually show up in the index.

Has anyone been able to get NSUserActivity to show up on spotlight with the lastest beta? (Beta 6)


I still can't get it to work, but it's fine with CoreSpotlight API.

"still can't get it to work" meaning it's never worked for you in any of the betas? It worked fine for me in beta 4 and 5, 4 quit as the 5 released got nearer though.


I haven't tried my project in 6 yet, actually come to think of it, there was no iOS beta 6 released. So you actually mean 5....


Without seeing your code the only thing I can suggest is to make sure you did not set a `relatedUniqueIdentifier` if you do not have a corresponding Core Spotlight item, that prevented any of my results from appearing.

Same here, testing on Xcode Version 7.0 beta 6 (7A192o), NSUserActivity indexed item never ever shows in my search result. spent my last 4 hours on find solution, reset my simulator, and tweaking my code. nothing helps. Please advise.

NSUserActivity isn't working for me either on iOS 9.0 beta 5 on an iPad Mini 2 (Xcode 7 beta 6). I've tried all combinations of:

  • setting/not setting the .contentAttributeSet property
  • setting/not setting .userInfo (though I don't need it for this case) with and without .requiredUserInfoKeys
  • also setting .needsSave = YES
  • setting/not setting the keywords property
  • setting/not setting the thumbnailURL (which incidentally works just fine when using CSSearchableItem).
  • setting eligibleForHandoff = YES (and NO)


CSSearchableItem works just fine on this device for other data we're indexing.


Code is below:


NSUserActivity* shortcut = [[NSUserActivity alloc] initWithActivityType:@"com.example.myapp.show_settings"];
shortcut.eligibleForHandoff = NO;
shortcut.eligibleForSearch = YES;
shortcut.eligibleForPublicIndexing = YES;


shortcut.title = @"Some Title";


CSSearchableItemAttributeSet* attrs = [[CSSearchableItemAttributeSet alloc]
                                       initWithItemContentType:(__bridge NSString*)kUTTypeItem];
attrs.contentDescription = @"description";


shortcut.keywords = [NSSet setWithArray:@[@"keyword1",@"keyword2"]];


NSURLComponents* rsrc_path_parts = [NSURLComponents componentsWithURL:[[NSBundle mainBundle] resourceURL]
                                              resolvingAgainstBaseURL:YES];
rsrc_path_parts.path = [rsrc_path_parts.path stringByAppendingString:@"activitytype.png"];
attrs.thumbnailURL = rsrc_path_parts.URL;
shortcut.contentAttributeSet = attrs;
[shortcut becomeCurrent];


//Retain a reference so it makes into Spotlight
[_shortcut_activities addObject:shortcut];



At this point I have to conclude NSUserActivity for Spotlight just doesn't work.

Same here. I feel like I've "tried everything" without success.

This is all working fine for me now.


The missing part of the puzzle was that if you set a relatedUniqueIdentifier on an NSUserActivity, it doesn't get indexed. Seems like Apple didn't envisage this usage pattern so we've been advised that if you want to do this (i.e to be able to de-duplicate between CoreSpotlight and NSUserActivity) you should create a CoreSpotlight entry first with the relevant uniqueIdentifier.


Any updates from attributes in the NSUserActivity make it into Spotlight.


This works fine on the simulator and devices for me, both with b5 and tested with Xcode b6.


Other things I found important ( but it looks like you're already doing them)

Retaining the activity

Not using the userActivity property of viewController as this seems to be at the mercy of iOS so can lose its userInfo.


It may be worth trying with a different contentType. I remember back in the early betas some content types didn't seem to get indexed.

If you are setting a relatedUniqueIdentifier on a NSUserActivity, that identifier must already have been indexed with CoreSpotlight. Would that explain the behavior you're seeing?

Hi pdm, it doesn't. The exact code I'm using (santized parameters of course) is what I included above. These NSUserActivity instances are shortcuts into particular sections of the app so there's no need to relate them to anything else.


Since they're global shortcuts, I'm creating them in didFinishLaunchingWithOptions and adding them to an NSMutableArray that's strongly held. I also tried creating them in my root view controller instead with no better luck.

I copy/pasted the code you included into a new Single View project into the viewDidLoad method (just since it was there in the template), added a shortcut_activities property on the VC, initialized it to a mutable array (if it hadn't been initialized already), built, ran, and searched for "keyword1", "keyword2", and "some". In all cases I got a result in Spotlight. So in the build that I'm using it's working (granted my build is slightly newer than beta 5). But I'm fairly confident that it'd be working in beta 5 as well.


Can you check in the debugger that your array is actually non-nil? Could you also check the value of +[CSSearchableIndex isIndexingAvailable]? I believe iPad mini 2 is one of the supported devices, but it would be good to include that check regardless.


If you're still not able to get it to work, I'd suggest filing a bug report and attaching a sample app.

Hey pdm (thanks for your help btw). I feel really dumb...we were checking isIndexing, but the NSMutableArray wasn't getting alloc/init'd before use. So the addObject had no effect of retaining a reference.


Correcting that, we get what 1 out of 5 activities indexed. The code above is actually run inside a "for in" block that creates 5 "shortcut" activities and calls becomeCurrent on each one inside the loop before adding them to the array. It looks like whatever activity is in the last iteration of the loop is the one that gets created. I'm guessing that's because the becomeCurrent calls are too close together timewise?

If I had a $1 for every time I felt dumb for the same reason.... 🙂


NSUserActivity is intended to be just that, based on actual user activity. The fact that you're doing something in a loop indicates to me you're likely using the wrong API. I think you should be using CoreSpotlight instead of NSUserActivity. I would recommend switching to those APIs (which shouldn't be a large change) and see how that works out.


Then as the user actually activates the activities, then generate a single NSUserActivity (using the relatedUniqueIdentitifer to link it to your previous CoreSpotlight item that you indexed). This will give you the best results becase we'll see that you have indexed activity (CoreSpotlight) that the user has actually engaged with (NSUserActivity) and this gives us a hint that the CS items are valuable to the user, which may lead to your search results being promoted higher in search results.

Hello pdm,


I have a similiar problem like jasonjwwilliams. I have a list of Restaurants, i wish to index them for my users. Actually I started with CoreSpotlight indexing because it feels like more powerful. It correctly indexed every restaurant for me and when i searched, for instance, "restarunt a", it did show me all the information about that restaurant, which is good.


But the problem i had is when user clicks on the search result, indexed by "CoreSpolight", such as "restaurant a". I wish to bring them to the restaurant detail page. However, the only "userInfo" i can get from method


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


of that userActivity is the unique idenfitier, which is not enough for me to do that. So i tried to user NSUserActivity for indexing that list. Then i ended up exactly like Jason, it only indexed the last item in my array.


From the WWDC Search Api video, seems like they recommending us to not using any loader and show the result directly, but it feels like CoreSpotlight indexing can't carry enough information for doing that.


Please let me know if there is anything i did wrong, or I could have done. I have been struggling on this feature for a coupe of days. Please advise.


Thanks.

Hi pdm. Well not really...the docs on using Spotlight all urge you to use NSUserActivity to make shortcuts into your app available.


But there are numerous parts of the app the user won't know are there if they never use them (and hence haven't visited them yet so they would be indexed)...which obviates the recommendation to put shortcuts into Spotlight using NSUserActivity. For example, we have a Forgot Password mechanism in the app that the user may have trouble finding. It would be natural for them to type "<app> reset password" to figure out how to do it. So we'd like to preindex that activity for them, since the reason they're searching is because they haven't been there and can't figure out how to. Does that make sense?

NSUserActivity results
 
 
Q