Search code examples
iosobjective-ccorespotlightnsuseractivitysirishortcuts

Siri Shortcut with NSUserActivity - activity deletion not working


I am using NSUserActivity and CoreSpotlight APIs following closely along with the NSUserActivity example code sections from the WWDC Introduction to Siri Shortcuts and Building for Voice with Siri Shortcuts videos, but I'm having problems deleting activities once my user deletes the corresponding data. My app is a book reading app where users can download and read books, so I want to have shortcuts to each book the user has downloaded, but delete the shortcut when/if they delete the book.

I have code here defining the NSUserActivity and its associated properties:

self.activity = [[[NSUserActivity alloc] initWithActivityType: @"Read a book"] autorelease];
self.activity.eligibleForSearch = true;
self.activity.eligibleForHandoff = true;
self.activity.eligibleForPublicIndexing = true;
self.activity.userInfo = @{ @"productID" : productID };
self.activity.requiredUserInfoKeys = [NSSet setWithArray: @[@"productID"]];
if (@available(iOS 12.0, *))
{
    self.activity.eligibleForPrediction = true;
    self.activity.suggestedInvocationPhrase = @"Read";
    self.activity.persistentIdentifier = NSUserActivityPersistentIdentifier(productID);
}

I also have code defining a CSSearchableItemAttributeSet, its associated properties, connecting it to the NSUserActivity, and making it active:

CSSearchableItemAttributeSet *attributes = [[[CSSearchableItemAttributeSet alloc] initWithItemContentType: (NSString *)kUTTypeItem] autorelease];
attributes.title = bookTitle;
attributes.keywords = @[keywords];
attributes.contentDescription = author;
attributes.thumbnailData = [NSData dataWithContentsOfURL: self.bookCover];
attributes.domainIdentifier = productID;
self.activity.contentAttributeSet = attributes;
self.userActivity = self.activity;
[self.activity becomeCurrent];

I've found out through research that using attributes.relatedUniqueIdentifier gets rid of the userInfo dictionary, and in my case this makes the shortcut not show up at all, so I am using attributes.domainIdentifier instead.

Now in another file I go to delete the shortcut. I've tried using this code which uses the self.activity.persistentIdentifier property:

if (@available(iOS 12.0, *)) {
    [NSUserActivity deleteSavedUserActivitiesWithPersistentIdentifiers: @[NSUserActivityPersistentIdentifier(productID)] completionHandler: ^{}];
}

I've also tried using this code which uses the attributes.domainIdentifier property:

[[CSSearchableIndex defaultSearchableIndex] deleteSearchableItemsWithDomainIdentifiers: @[productID] completionHandler: ^(NSError * _Nullable error) {}];

And neither of these solutions have worked. In both cases I have checked the productID parameter that is passed into the functions and it has beent the correct value both times.

Is there something I'm doing wrong or something I'm missing?

Thank you all in advance for the help. This is my first post, let me know if I need to provide more information.


Solution

  • I figured out what I was missing. I needed to create a CSSearchableItem, set its uniqueIdentifier and domainIdentifier properties to be equal to the NSUserActivity's. Then I needed to index the CSSearchableItem.

    This is the code I was missing:

    attributes.relatedUniqueIdentifier = productID
    
    CSSearchableItem *item = [[[CSSearchableItem alloc] init] autorelease];
    item.uniqueIdentifier = productID;
    item.domainIdentifier = productID;
    [[CSSearchableIndex defaultSearchableIndex] indexSearchableItems: @[item] completionHandler: ^(NSError * _Nullable error) {}];