IOS 9 App Search tutorial

Source: Internet
Author: User
Tags home screen

IOS 9 App Search tutorial

For a long period of time, iOS Spotlight is a big pitfall. Although users can use it to search for your App, they cannot see the content-what they really care about. Now, when users want to read the content of an App, they can only go back to the Home screen and flip the screen, find the App, open the App, search for what they want-assuming your App implements the search function.

For more sophisticated users, you may use Siri or Spotlight to open your App. However, no tool allows users to search for content in the "unofficial Apple App. That is to say, Apple can find the address book, memo, information, emails, and other content in apps that support the search function in Spotlight. You only need to click the search result to directly access the corresponding content. This is really unfair!

Sometimes Apple keeps some interesting features dedicated to itself, such as Spotlight. The good news is that every time Apple developers call a function and feel that they can release it, they will try it out, for example, App extensions in iOS 8.

In iOS 9, Apple released a cool feature for us. Third-party developers can now search for their App content in Spotlight!

In this tutorial, you will learn the power of App Search and how to integrate it into your own App.

App Search API

In iOS 9, App Search consists of three parts. Each part is divided into independent APIs for different purposes, but they can also be used with other parts:

NSUserActivity Core Spotlight Web markupNSUserActivity

NSUserActivity is used in App Search, which is a flexible and small function. NSUserActivity is used in iOS 8 Handoff.

In iOS 9, NSUserActiviy adds some new attributes to support App Search. Theoretically, if a task can be converted into an NSUserActivity and transferred to another device, it can also be converted into a search item and processed on the same device. This makes it possible to index activity, status, and navigation points on the App so that users can search for them in Spotlight.

For example, a tourism App may index the hotels you have viewed, and a news App will index the articles you have browsed.

Note: This tutorial does not involve Handoff. We will only discuss how to create searchable content after a content is browsed. If you want to familiarize yourself with Handoff, read the Getting Started with Handoff tutorial.

Core Spotlight

Core Spotlight is also the most commonly used concept in App Search. It is used to index content in storage apps such as emails and memos. It allows users to search for previously accessed content, and can also be used to build a large set of searchable content at a time.

You can think of Core Spotlight as a database dedicated for search. It provides fine-grained control over the content added to the search index, such as what the content is, when it is added, and how it is added to the search index. You can retrieve any type of content, including files, videos, messages, and so on. You can also update and Remove entries in the search index.

Core Spotlight provides the best way to fully search the internal content of an App.

This tutorial focuses on getting Spotlight search results using the NSUserActivity object mentioned above. The full version of this tutorial is in iOS 9 Tutorials, which describes how to use Core Spotlight to fully retrieve your content.

Web markup

The third aspect of App Search is Web Markup, which allows apps to mirror their content to a Web site. For example, Amazon, you can search for thousands of products on sale, or even products on raywenderlich.com. The web content is marked with standard tags. You can display the App content in Spotlight and Safari search results, or even directly link to your App.

This tutorial does not involve Web Markup. You can refer to Chapter 3 "Your App On The Web" in iOS 9 by Tutorials.

Start

The sample program you learned is called Colleagues, which simulates a company address book. It can add you to your contacts at the same time, rather than directly giving you a colleague's directory. For the sake of simplicity, it uses a local database consisting of a folder (storing profile pictures) and a JSON file (containing information about all company employees. In a production environment, you should use a network component to capture the data from the Web. As a tutorial, The JSON file is enough. Download and open the initial project. You do not need to do anything and compile and run it directly.

You will see a staff list. This is a small startup company with only 25 employees. Select Brent Reid to view the employee information. You can also see a list of other persons in the department where Brent Reid is located. It is an extension of the App-in fact, it is very simple!

The search function adds a lot of colors to the App. But now, you cannot even search in the App. You do not need to add the search function to the App. Instead, you can use Spotlight to add a search function from outside the App.

Sample project

Take some time to familiarize yourself with the code of the sample project. There are two targets in the project. One is Colleagues, that is, the App itself; the other is EmployeeKit, which is responsible for interacting with the staff database.

In Xcode, expand the EmployeeKit folder and open Employee. swift. This is a model class of employee information and defines a series of related attributes. The Employee object is instantiated using a JSON object, which is from the employees. json file in the Database folder.

Enable EmployeeService. swift. An extension is declared in the file header, and there is a destroyEmployeeIndexing () method in the extension. This method is marked with the TODO mark. You will implement this method later. This method destroys all the displayed indexes.

There is a lot of content in the Target of EmployeeKit, but it is irrelevant to App Search, so we will not talk about it much. Of course, you can take a look.

Open AppDelegate. swift in the Colleagues folder. Note that there is only one method in it:
Application (_: didfinishlaunchingwitexceptions :). This method determines whether Setting. searchIndexingPreference is set to. Disabled. If yes, all existing search indexes are deleted.

You do not need to do anything except to know that such a configuration item exists. You can modify this setting through Colleagues in the iOS setup program.

The visit is over. Next, you need to modify the code in View Controller.

Search records that have been browsed

When implementing App Search, NSUserActivity is always the first to be implemented, because:

It is the simplest. Creating an NSUserActivity instance is as simple as setting several attributes.

When you use NSUserActivity to represent a user activity, iOS sorts the content so that the search result gives priority to frequently accessed content.

It is similar to Handoff.

Now, let's see how simple NSUserActivity is!

NSUserActivity implementation

Select the EmployeeKit folder, and then select File \ New \ File ..., Select the iOS \ Source \ Swift File template and click Next. Name the file "EmployeeSearch. swift" and ensure that its Target is "EmployeeKit.

In this file, first import CoreSpotlight:

import CoreSpotlight

Then define an extension of the Employee:

extension Employee {  public static let domainIdentifier = "com.raywenderlich.colleagues.employee"}

The anti-domain string is used to uniquely identify a type of activity to which NSUserActivity belongs. Next, add a computing attribute after domainIdentifier:

public var userActivityUserInfo: [NSObject: AnyObject] {  return ["id": objectId]}

This dictionary uniquely identifies an Activity ). Then add a computing attribute named userActivity:

public var userActivity: NSUserActivity {  let activity = NSUserActivity(activityType: Employee.domainIdentifier)  activity.title = name  activity.userInfo = userActivityUserInfo  activity.keywords = [email, department]  return activity}

This attribute is used to easily create an NSUserActivity instance based on an Employee. It creates an NSUserActivity object and assigns values to the following attributes:

ActivityType: Type of the activity. You will use it later to identify the NSUserActivity instance that iOS delivers to you. Apple recommends that this value adopt the anti-Domain Name naming rules.

Title: name of the activity-this will be used for display as the main name in the search results.

UserInfo: a dictionary used to store any data you want to transmit. When your App receives an activity, for example, if you click a search result from Spotlight, you can obtain the dictionary. You will store the unique ID of a colleague in this dictionary so that the App can display the correct colleague information.

Keywords: A list of localized keywords used as search keywords.

Then, we will use the userActivity attribute just defined to search for colleague records. Because these codes are in the EmployeeKit framework, we need to compile the framework to use them in the Colleagues App.

Compile the project by Command + B.

Open EmployeeViewController. swift and add the code at the end of the viewDidLoad () method:

let activity = employee.userActivityswitch Setting.searchIndexingPreference {case .Disabled:  activity.eligibleForSearch = falsecase .ViewedRecords:  activity.eligibleForSearch = true}userActivity = activity

The above Code reads the userActivity attribute -- this attribute was added when we defined the Employee extension. Then, check the search settings of the App.

If the search is disabled, Mark activty as unavailable for search. If this parameter is set to ViewedRecords, the activity is marked as usable for search.

Finally, set the userActivity attribute of View Controller to the userActivity of employee.

Note: The userActivity attribute of View Controller inherits from UIResponder. This attribute is added to iOS 8 by Apple to support Handoff.

The updateUserActivityState () method should also be overwritten. In this way, you can obtain the required data only when a search result is selected.

Add this method after the viewDidLoad () method:

override func updateUserActivityState(activity: NSUserActivity) {  activity.addUserInfoEntriesFromDictionary(    employee.userActivityUserInfo)}

In the life cycle of UIResponder, the system will call this method multiple times. You should keep updating the activity in this method. In our example, you only need to pass the userActivityUserInfo dictionary containing the objectId of the employee to the activity.

Okay! Now, when the search settings are enabled, When you browse a colleague, the browsing history is recorded and can be used for search.

On the simulator or device, open the setup program and find Colleagues. Change the Indexing settings to Viewed Records.

Now compile and run the program and select Brent Reid.

OK, it seems that nothing novel has happened, but without your knowledge, the Brent activity has been added to the search index. Return to the Home screen (shift + command + H), drag the screen from the drop-down list or right to open Spotlight. Enter brent reid in the search bar.

"Brent Reid" is displayed! If you do not see it, you may need to scroll down the list. If you click this Brend Reid, it will move to the top of the list so that you can search for the same keyword next time.

Although the results have been quite good so far, the search results are a bit tasteless.

What can we do besides displaying a name? Now let's start exploring Core Spotlight.

Show more information in search results

NSUserActivity has a contentAttributeSet attribute. The type of this attribute is CSSearchableItemAttributeSet, which allows you to describe your content using a series of attributes. View the CSSearchableItemAttributeSet class reference. You can find many methods that use these attributes to describe the content.

Is the search result we need. Each part is marked with the attribute name:

You have set the title attribute of NSUserActivity as you can see. The other three attributes, thumbnailData, supportsPhoneCall, and contentDescription, are all set through CSSearchableItemAttributeSet.

Open EmployeeSearch. swift and import MobileCoreServices in the file header:

import MobileCoreServices

MobileCoreServices is required because a constant defined in it is required when we create a CSSearchableItemAttributeSet object. You have already imported CoreSpotlight. This framework is also required. All its APIs use CS as the prefix.

Still in EmployeeSearch. swift, add new computing attributes in the Employee extension:

public var attributeSet: CSSearchableItemAttributeSet {  let attributeSet = CSSearchableItemAttributeSet(    itemContentType: kUTTypeContact as String)  attributeSet.title = name  attributeSet.contentDescription = "\(department), \(title)\n\(phone)"  attributeSet.thumbnailData = UIImageJPEGRepresentation(    loadPicture(), 0.9)  attributeSet.supportsPhoneCall = true  attributeSet.phoneNumbers = [phone]  attributeSet.emailAddresses = [email]  attributeSet.keywords = skills  return attributeSet}

When initializing CSSearchableItemAttributeSet, you need to provide an itemContentType parameter, and we pass a kUTTypeContact (this constant is defined in the MobileCoreServices framework. For details about this constant, refer to the UTType reference of Apple ).

AttributeSet contains some data related to the current employee search: The title is from the title of NSUserActivity, And the contentDescription includes the Department, title, and phone number of the employee, thumbnailData calls the loadPicture () method and converts the result to NSData.

To display the "call" button, we must set supportsPhoneCall to true and assign an array to the phoneNumbers attribute. Finally, we set the email address and use the colleague's skills (skill) as the key word.

Now all the data is ready, and Core Spotlight will search for the data and add it to the search results. In this way, you can search for colleagues' names, departments, titles, phone numbers, emails, and even skills.

It is still EmployeeSearch. swift. Add the following statement before returning userActivity:

activity.contentAttributeSet = attributeSet

This code tells NSUserActivity to use this information as the value of the contentAttributeSet attribute.

Compile and run. View the personal information of Brent Reid for the index to take effect. Return to the Home screen, pull out Spotlight, and search for brent reid. If your previous search results still exist, you only need to clear and search again.

Oh, aren't you surprised that there are too few codes to implement?

Okay! Now Spotlight can search for colleagues as we think. However, we seem to have missed something... Nothing happens when you try to open the App through search results.

Open Search Results

The ideal user experience is to directly open the App and display relevant content. In fact-this is a requirement-Apple will rank the top search results for apps that can start and display useful information.

By assigning an activityType and a userInfo object to the NSUserActivity object, you have paved the way for subsequent work in the previous section.

Open AppDelegate. swift and add
One application (_: continueUserActivity: restorationHandler :) method:

func application(application: UIApplication,  continueUserActivity userActivity: NSUserActivity,  restorationHandler: ([AnyObject]?) -> Void) -> Bool {  return true}

When you select a search result, this method will be called-this method will also be used by Handoff to receive activities from other devices.

Before this method returns true, add the following statement:

guard userActivity.activityType == Employee.domainIdentifier,  let objectId = userActivity.userInfo?["id"] as? String else {    return false}

The guard statement checks whether the activityType is the expected type (used to process the Employee activity) and obtains objectId from userInfo. If one of the two conditions does not meet the conditions, false is returned, notifying the system that the activity will not be processed.

Then, after the guard statement, replace the return true statement:

if let nav = window?.rootViewController as? UINavigationController,  listVC = nav.viewControllers.first as? EmployeeListViewController,  employee = EmployeeService().employeeWithObjectId(objectId) {    nav.popToRootViewControllerAnimated(false)    let employeeViewController = listVC      .storyboard?      .instantiateViewControllerWithIdentifier("EmployeeView") as!        EmployeeViewController    employeeViewController.employee = employee    nav.pushViewController(employeeViewController, animated: false)    return true}return false

After obtaining the id, your goal is to use EmployeeViewController to display the matched colleague information.

The above code is slightly messy, but you can imagine the App design. There are two View controllers in the App. One is the list of colleagues, and the other is the list of colleagues. The code above first rounds the View Controller stack of the navigation controller back to the list interface, and then pushes a detail window of this colleague.

If the view cannot be rendered for some reason, the method returns false.

OK, compile and run! Select Cary Iowa from the list and return to the Home screen. Call Spotlight to search for Brent Reid. Find the result and click it. The App opens and you can see that the Cary details interface quickly transits to the Bent details interface. Good job!

Delete entries from search Indexes

Return to the topic of the App. Imagine that on a stormy day, a colleague was fired because he tied his boss to a wall with tape. Obviously, you do not want to have any relationship with this person in any case, so you must delete it from the Colleagues search index together with other people who leave the company.

Because it is just an example App, you can delete the entire index when the App's index settings are disabled.

Open EmployeeService. swift and add the Import Statement in the file header:

import CoreSpotlight

Locate destoryEmployeeIndexing () and replace the TODO Annotation:

CSSearchableIndex  .defaultSearchableIndex()  .deleteAllSearchableItemsWithCompletionHandler { error in  if let error = error {    print("Error deleting searching employee items: \(error)")  } else {    print("Employees indexing deleted.")  }}

This method without parameters will delete the index database of the entire App. Good!

Now let's test it. Perform the following steps to test whether the index has been deleted as expected:

Compile and run the program.

Use Xcode to terminate the program.

In the simulator or device, enable \ Colleagues and set Indexing to Viewed Records.

Open the App again and select a new colleague to make the index take effect.

Return to the Home screen to bring up Spotlight.

Search for browsed colleagues and wait for the index item to appear.

Go back to Settings \ Colleagues and set Indexing to off.

Exit the App.

Open the App again. This will clear the search index.

Return to the Home screen to bring up Spotlight.

Search for browsed Colleagues and you will find that there are no search results related to the Colleagues App.

It's too easy to delete the entire search index. But what if you want to delete only a single record? Fortunately, there are two APIs that allow you to delete records more accurately:

The deleteSearchableItemsWithDomainIdentifiers (_: completionHandler :) method allows you to delete a group of indexes with the same domain ID.

The deleteSearchableItemsWithIdentifiers (_: completionHandler :) method allows you to specify the record to be deleted with a unique ID.

That is to say, if the record you index has multiple types, the global ID (in the same App group) must be unique.

Note: if you cannot guarantee that the cross-type ID is unique, for example, your ID is obtained through the auto-growth type in the database, you can take a simple approach, add a type prefix before the record ID. For example, if you have a contact record ID of 123 and an order record ID of 123, you can set their unique IDs to contact.123 and order.123.

If you encounter any problems during the running process, you can download the final project from here.

What to do next?

This iOS 9 App Search tutorial introduces a simple but powerful method for searching the internal content of an App using User Activity in iOS 9. The search content is never restricted-you can use this method to search for navigation points in the App.

Imagine a CRM App that has many windows, such as contacts, orders, and tasks. With User Activity, you can reach these windows at any time. You can search for orders and directly jump to an order page of the App. This function is very useful, especially when your App has many levels of navigation.

There are many unique ways to push content to your users. To break through the limitations of sandbox, we need to teach users to use this powerful function.

This tutorial is a lite version of chapter 2nd of iOS 9 by Tutorials. If you want to learn how to use Core Spotlight to retrieve large datasets, or learn the Web Content of iOS 9, please read this book!


Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.