Handling searchable item selection

If a user taps on a search result for one of the items you indexed manually, the application(_:continue:restorationHandler:) method is called on AppDelegate. This is the same method that's used for user activities, but the internal handling is not quite the same.

In the original code to continue user activities, the user activity's title property was used to determine the appropriate action. Since searchable items don't have this property, a different approach will have to be implemented. To decide whether the user activity that is passed to application(_:continue:restorationHandler:) is a searchable item or a user activity, you can read the activity type. If the user activity was originally a searchable item, the activity type should be equal to CSSearchableItemActivityIdentifier. If you receive a user activity with this activity type, you should take action accordingly.

Update your code in AppDelegate as follows and make sure to import CoreSpotlight:

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

  if let identifier = userActivity.userInfo?[CSSearchableItemActivityIdentifier] as? String, userActivity.activityType == CSSearchableItemActionType {

    return handleCoreSpotlightActivity(withIdentifier: identifier)
  }

  // existing implementation
}

func handleCoreSpotlightActivity(withIdentifier identifier: String) -> Bool {
  guard let url = URL(string: identifier),
    let objectID = persistentContainer.persistentStoreCoordinator.managedObjectID(forURIRepresentation: url),
    let object = try? persistentContainer.viewContext.existingObject(with: objectID)
    else { return false }

  if let movie = object as? Movie {
    return handleOpenMovieDetail(withName: movie.name!)
  }

  if let familyMember = object as? FamilyMember {
    return handleOpenFamilyMemberDetail(withName: familyMember.name!)
  }
  return false
}

The updated version of application(_:continue:restorationHandler:) checks whether it received a searchable item. If it did, a special method is called. This method uses the persistent store to convert the string identifier to a managed object ID which is then used to ask the managed object context for the corresponding object. If all of this succeeds, we attempt to cast the fetched object to either a movie or a family member, and if this succeeds, one of the existing handlers is called. If none of the casts succeed, it was not possible to continue the activity, so the method returns false.

Note that this implementation assumes that you did the exercise that was proposed earlier in the chapter so handleOpenFamilyMemberDetail(withName:) and handleOpenMovieDetail(withName:) do not exist in the project. Refer to this chapter's code bundle to see a suggested implementation for both of these methods.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset