2. Using Framework Core Spotlight
Another set of APIs in iOS 9 that supports user content search in your app is the Core Spotlight framework. This framework has a database design style and lets you provide more information about the content you want it to be searched for.
Before you can use the Core Spotlight framework, we need to connect the project to this framework. In Project Navigator , select the project and open the Build Phases tab at the top. Next, open the Link Binary With Libraries section and click on the + sign. In the menu that appears, find CoreSpotlight and connect the project to this framework. Repeat these steps with MobileCoreServices framework.
Next, to make sure that the search results our application provides are from Core Spotlight, delete the app from your test device or iOS Simulator, and comment the following lines in the DetailViewController
class:
1 | activity.becomeCurrent () |
Finally, open the MasterViewController.swift file and add the following lines before defining the Show
structure:
1 2 | import CoreSpotlight import MobileCoreServices |
Next, add the following code to viewDidLoad
of the MasterViewController
class:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | var searchableItems: [CSSearchableItem] = [] for show in objects { let attributeSet = CSSearchableItemAttributeSet (itemContentType: kUTTypeItem as String) attributeSet.title = show.name let dateFormatter = NSDateFormatter () dateFormatter.timeStyle = .ShortStyle attributeSet.contentDescription = show.genre + "n" + dateFormatter.stringFromDate (show.time) var keywords = show.name.componentsSeparatedByString ("") keywords.append (show.genre) attributeSet.keywords = keywords let item = CSSearchableItem (uniqueIdentifier: show.name, domainIdentifier: "tv-shows", attributeSet: attributeSet) searchableItems.append (item) } CSSearchableIndex.defaultSearchableIndex (). IndexSearchableItems (searchableItems) {(error) -> Void print if error! = nil { print (error? .localizedDescription) } else { // Items were indexed successfully } } |
Before verifying this code, analyze each step in the for
loop.
- Create a
CSSearchableItemAttributeSet
object, passing an item to the content type parameter. If the search results link to an image, for example, you will pass thekUTTypeImage
. - You assign the
title
attribute of the attribute set to the value of the show name. LikeNSUserActivity
, this title is what will appear at the top of the search results. - Next, create a description string and assign this value to the
contentDescription
attribute of the set attribute. This string will be displayed below the Spotlight result title. - You initialize an array containing search result keywords like you did with
NSUserActivity
. - Finally, you create a
CSSearchableItem
with a unique item identifier, the unique domain identifier to group items together and a set attribute. UnlikeNSUserActivity
, which returns user activity from the search results, the unique identifiers you use forCSSearchableItem
are the only information you receive from the system when your search results are selected from the user. You need to use these identifiers to restore your app to the most accurate state.
Each time you initialize a CSSearchableItem
for TV programs, you index them using the indexSearchableItems(_:completionHandler:)
in the default CSSearchableIndex
object.
Build and run the app, all programs will be cataloged by Spotlight. Navigate to the search frame and search for a program.
The search results from Core Spotlight are handled by the same methods as NSUserActivity
, but this process is slightly different. When a CSSearchableItem
is selected from the search results, the system will create an NSUserActivity
object for you that contains the unique identifier of the selected item.
In the application(_:continueUserActivity:restorationHandler:)
of appdelegate, you can use the following method to get the information you need from the search results from Core Spotlight:
1 2 3 4 5 6 7 8 | if userActivity.activityType == CSSearchableItemActionType { if let identifier = userActivity.userInfo? [CSSearchableItemActivityIdentifier] as? String { // Use identifier to display content correct for this search result return true } } |
A good way to index content from your app with the Core Spotlight framework is to delete items when they are no longer needed. Class CSSearchableIndex
provides 3 methods to delete the searched items:
-
deleteAllSearchableItemsWithCompletionHandler(_:)
-
deleteSearchableItemsWithDomainIdentifiers(_:completionHandler:)
-
deleteSearchableItemsWithIdentifiers(_:completionHandler:)
As an example, add the following code to the end of the viewDidLoad
function of the MasterViewController
class:
1 2 3 4 5 6 7 8 | CSSearchableIndex.defaultSearchableIndex (). DeleteSearchableItemsWithDomainIdentifiers (["tv-shows"]) {(error) -> Void print if error! = nil { print (error? .localizedDescription) } else { // Items deleted successfully } } |
Build and run the app again. When you try to find any program, there is no return result because they have been deleted from the table of contents.
3. Combining NSUserActivity
and Core Spotlight
A new thing added to the NSUserActivity
class in iOS 9 is the contentAttributeSet
attribute. This property allows you to assign a CSSearchableItemAttributeSet
, as well as the one you created earlier. This attribute set allows your search results for the NSUserActivity
object to display the same details as the search results from Core Spotlight.
Start by adding the following import section at the top of the DetailViewController.swift file:
1 2 | import CoreSpotlight import MobileCoreServices |
Next, update the configureView
function in the DetailViewController
class in the following way:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | func configureView () { // Update user interface for the detail item. if self.nameLabel! = nil && self.detailItem! = nil { self.nameLabel.text = detailItem.name self.genreLabel.text = detailItem.genre let dateFormatter = NSDateFormatter () dateFormatter.timeStyle = .ShortStyle self.timeLabel.text = dateFormatter.stringFromDate (detailItem.time) let activity = NSUserActivity (activityType: "com.tutsplus.iOS-9-Search.displayShow") activity.userInfo = ["name": detailItem.name, "genre": detailItem.genre, "time": detailItem.time] activity.title = detailItem.name var keywords = detailItem.name.componentsSeparatedByString ("") keywords.append (detailItem.genre) activity.keywords = Set (keywords) activity.eligibleForHandoff = false activity.eligibleForSearch = true //activity.eligibleForPublicIndexing = true //activity.expirationDate = NSDate () let attributeSet = CSSearchableItemAttributeSet (itemContentType: kUTTypeItem as String) attributeSet.title = detailItem.name attributeSet.contentDescription = detailItem.genre + "n" + dateFormatter.stringFromDate (detailItem.time) activity.becomeCurrent () } } |
Build and run the app, open some programs. When you search for a program, you will see that your results, created with NSUserActivity
, contain the same level of detail as the search results from Core Spotlight.
Epilogue
In this tutorial, you learned how to make an application whose content can be accessed via iOS Spotlight using the NSUserActivity
class and Core Spotlight framework. The author also shows us how to index content from the app using both of these APIs and how to restore the app state when a search result is selected from the user.
The new search APIs introduced with iOS 9 are easy to use and make your application content easier to find and more accessible to your users.
Source IDE Academy via code.tutsplus.com
Source IDE Academy via code.tutsplus.com