Вступление
На WWDC 2015 Apple официально анонсировала iOS 9 . В дополнение ко многим новым функциям и улучшениям, это обновление также дает разработчикам возможность сделать контент своих приложений более доступным и доступным с помощью поиска Spotlight. Новые API, доступные в iOS 9, позволяют индексировать любой контент или состояние интерфейса в вашем приложении, делая его доступным для ваших пользователей через Spotlight. Три компонента этих новых API поиска:
- класс
NSUserActivity
, предназначенный для просмотра содержимого приложения - платформа Core Spotlight , предназначенная для любого содержимого приложения
- веб-разметка, предназначенная для приложений, содержимое которых отображается на веб-сайте
В этом руководстве я собираюсь показать вам, как вы можете использовать класс NSUserActivity
и инфраструктуру Core Spotlight в своих собственных приложениях.
Предпосылки
Это руководство требует, чтобы вы работали с Xcode 7 в OS X 10.10 или более поздней версии. Чтобы следовать за мной, вам также нужно скачать стартовый проект с GitHub .
1. Использование NSUserActivity
В первой части этого руководства я покажу вам, как можно индексировать содержимое приложения с помощью класса NSUserActivity
. Этот API является тем же, который используется для Handoff, функции, представленной в iOS 8 в прошлом году, и обрабатывает как сохранение, так и восстановление текущего состояния приложения.
Если вы раньше не работали с NSUserActivity
, то я предлагаю вам сначала прочитать мой учебник, посвященный основам NSUserActivity
и NSUserActivity
затем продолжить.
Прежде чем писать какой-либо код, откройте стартовый проект и запустите приложение в iOS Simulator или на тестовом устройстве. На этом этапе вы увидите, что приложение просто отображает список из четырех телешоу и страницу с подробностями для каждого из них.
Для начала откройте стартовый проект и перейдите к DetailViewController.swift . Замените метод DetailViewController
класса DetailViewController
следующей реализацией:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
func configureView() {
// Update the 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()
activity.becomeCurrent()
}
}
|
Код, который настраивает метки в контроллере представления, не изменяется, но давайте пройдемся по коду активности пользователя шаг за шагом:
- Вы создаете новый объект
NSUserActivity
с уникальным идентификатором com.tutsplus.iOS-9-Search.displayShow . Стартовый проект уже настроен на использование этого идентификатора, поэтому обязательно оставьте этот идентификатор без изменений. - Затем вы назначаете словарь
userInfo
пользовательской активности. Это будет использовано позже для восстановления состояния приложения. - Вы присваиваете свойству
title
активности строковое значение. Это то, что будет отображаться в результатах поиска Spotlight. - Чтобы обеспечить возможность поиска по контенту не только по его названию, вы также предоставляете набор ключевых слов. В приведенном выше фрагменте кода набор ключевых слов включает в себя каждое слово из названия шоу, а также его жанр.
- Затем вы устанавливаете ряд свойств объекта
NSUserActivity
чтобы сообщить операционной системе, для чего вы хотите использовать это действие пользователя. В этом уроке мы рассматриваем только компонент поиска API, поэтому мы отключаем Handoff и включаем поиск . - Наконец, вы вызываете метод
becomeCurrent
для активности пользователя, после чего она автоматически добавляется в индекс результатов поиска устройства.
В приведенной выше реализации вы, вероятно, заметили две строки в комментариях. Хотя мы не будем использовать эти свойства в этом руководстве, важно знать, для чего используется каждое свойство.
- В вышеописанной реализации активность пользователя и результат поиска создаются для каждого отдельного шоу только после открытия приложения. Когда вы делаете свою пользовательскую активность
eligibleForPublicIndexing
, Apple начинает отслеживать использование и взаимодействие этой конкретной деятельности из результатов поиска пользователя. Если результатом поиска пользуются многие пользователи, Apple продвигает активность пользователей в свой собственный облачный индекс . Как только пользовательский актив попадает в этот облачный индекс, он доступен для поиска любому, кто установил ваше приложение, независимо от того, открыли ли они конкретный контент или нет. Это свойство должно иметь значениеtrue
для действий, доступных всем пользователям вашего приложения. - Пользовательское действие также может иметь необязательную
expirationDate
. Когда это свойство установлено, ваша пользовательская активность будет отображаться в результатах поиска только до указанной даты.
Теперь, когда вы знаете, как создать NSUserActivity
способное отображать результаты поиска в Spotlight, вы готовы его протестировать. Создайте и запустите свое приложение, и откройте несколько шоу в своем приложении. Сделав это, вернитесь на начальный экран (нажмите Command-Shift-H в симуляторе iOS) и проведите пальцем вниз или прокрутите до крайнего левого экрана, чтобы открыть вид поиска.
Начните вводить название одной из открытых вами выставок, и вы увидите, что она появляется в результатах поиска, как показано ниже.
Или введите жанр одного из шоу, которое вы открыли. Из-за ключевых слов, которые вы присвоили активности пользователя, это также приведет к тому, что шоу будет отображаться в результатах поиска.
Содержимое вашего приложения правильно проиндексировано операционной системой, и результаты отображаются в Spotlight. Однако при нажатии на результат поиска ваше приложение не приводит пользователя к соответствующему результату поиска. Он просто запускает приложение.
К счастью, как и в случае с Handoff , вы можете использовать класс NSUserActivity
для восстановления правильного состояния в вашем приложении. Чтобы сделать эту работу, нам нужно реализовать два метода.
AppDelegate
application(_:continueUserActivity:restorationHandler:)
в классе AppDelegate
как показано ниже.
1
2
3
4
5
6
|
func application(application: UIApplication, continueUserActivity userActivity: NSUserActivity, restorationHandler: ([AnyObject]?) -> Void) -> Bool {
let splitController = self.window?.rootViewController as!
let navigationController = splitController.viewControllers.first as!
navigationController.topViewController?.restoreUserActivityState(userActivity)
return true
}
|
Затем реализуйте метод restoreUserActivityState(_:)
в классе MasterViewController
.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
|
override func restoreUserActivityState(activity: NSUserActivity) {
if let name = activity.userInfo?[«name»] as?
let genre = activity.userInfo?[«genre»] as?
let time = activity.userInfo?[«time»] as?
let show = Show(name: name, genre: genre, time: time)
self.showToRestore = show
self.performSegueWithIdentifier(«showDetail», sender: self)
}
else {
let alert = UIAlertController(title: «Error», message: «Error retrieving information from userInfo:\n\(activity.userInfo)», preferredStyle: .Alert)
alert.addAction(UIAlertAction(title: «Dismiss», style: .Cancel, handler: nil))
self.presentViewController(alert, animated: true, completion: nil)
}
}
|
На момент написания этой статьи последняя версия Xcode 7 (бета-версия 3) содержала проблему, из-за userInfo
свойство userInfo
действия пользователя может быть пустым. Вот почему я обрабатываю любые ошибки и отображаю предупреждение с userInfo
, которое возвращается операционной системой.
Снова создайте и запустите приложение и выполните поиск шоу. Когда вы нажимаете на шоу в результатах поиска, приложение должно сразу перейти к контроллеру подробного представления и отобразить текущую информацию для шоу, которое вы нажали.
2. Использование Core Spotlight Framework
Еще один набор API-интерфейсов, доступных в iOS 9, чтобы сделать ваш контент доступным для поиска для пользователей, — это платформа Core Spotlight . Эта структура имеет дизайн в стиле базы данных и позволяет вам предоставлять еще больше информации о контенте, который вы хотите использовать для поиска.
Прежде чем вы сможете использовать платформу Core Spotlight, нам нужно связать проект со структурой. В Навигаторе проектов выберите проект и откройте вкладку « Фазы сборки » вверху. Затем разверните раздел « Связать двоичные файлы с библиотеками » и нажмите кнопку «плюс». В появившемся меню найдите CoreSpotlight и свяжите ваш проект со структурой. Повторите эти шаги для платформы MobileCoreServices .
Затем, чтобы убедиться, что результаты поиска, которые предоставляет наше приложение, получены из Core Spotlight, удалите свое приложение с тестового устройства или симулятора iOS и закомментируйте следующую строку в классе DetailViewController
:
1
|
activity.becomeCurrent()
|
Наконец, откройте MasterViewController.swift и добавьте следующие строки перед определением структуры Show
:
1
2
|
import CoreSpotlight
import MobileCoreServices
|
Затем добавьте следующий код в метод MasterViewController
класса MasterViewController
:
01
02
03
04
05
06
07
08
09
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 in
if error != nil {
print(error?.localizedDescription)
}
else {
// Items were indexed successfully
}
}
|
Прежде чем мы протестируем этот код, давайте пройдемся по каждому шагу цикла for
.
- Вы создаете объект
CSSearchableItemAttributeSet
, передавая тип содержимого для элемента. Например, если ваш результат поиска связан с фотографией, вы должны передать константуkUTTypeImage
. - Вы назначаете имя шоу свойству
title
набора атрибутов. Как и в случаеNSUserActivity
, этот заголовок будет отображаться в верхней части результатов поиска. - Затем вы создаете описательную строку и назначаете
contentDescription
свойствуcontentDescription
вашего набора атрибутов с возможностью поиска. Эта строка будет отображаться под заголовком результата в центре внимания. - Вы создаете массив ключевых слов из результата поиска так же, как вы делали это с
NSUserActivity
. - Наконец, вы создаете
CSSearchableItem
с уникальным идентификатором элемента, уникальным идентификатором домена для группировки элементов и набором атрибутов. В отличие отNSUserActivity
, который возвращает активность пользователя из результата поиска, уникальные идентификаторы, которые вы используете дляCSSearchableItem
являются единственной информацией, которую вы получаете из операционной системы, когда ваш результат поиска выбирается пользователем. Вам нужно использовать эти идентификаторы, чтобы вернуть ваше приложение в правильное состояние.
CSSearchableItem
для телешоу, вы индексируете их с помощью indexSearchableItems(_:completionHandler:)
CSSearchableIndex
объекта CSSearchableIndex
по умолчанию.
Создайте и запустите свое приложение, и все ваши шоу будут проиндексированы Spotlight. Перейдите к представлению поиска и найдите одно из шоу.
Результаты поиска Core Spotlight обрабатываются теми же методами, что и NSUserActivity
, но процесс немного отличается. Когда CSSearchableItem
выбран из результатов поиска, система создает для NSUserActivity
объект NSUserActivity
, который содержит уникальный идентификатор выбранного элемента.
В приложении делегата вашего приложения application(_:continueUserActivity:restorationHandler:)
метод application(_:continueUserActivity:restorationHandler:)
вы можете использовать следующую реализацию для получения необходимой информации из результатов поиска Core Spotlight:
1
2
3
4
5
6
7
8
|
if userActivity.activityType == CSSearchableItemActionType {
if let identifier = userActivity.userInfo?[CSSearchableItemActivityIdentifier] as?
// Use identifier to display the correct content for this search result
return true
}
}
|
При индексировании контента из приложения с помощью платформы Core Spotlight рекомендуется также удалять элементы, когда они больше не нужны. Класс CSSearchableIndex
предоставляет три метода для удаления элементов поиска:
-
deleteAllSearchableItemsWithCompletionHandler(_:)
-
deleteSearchableItemsWithDomainIdentifiers(_:completionHandler:)
-
deleteSearchableItemsWithIdentifiers(_:completionHandler:)
Например, добавьте следующий код в конец метода MasterViewController
класса MasterViewController
:
1
2
3
4
5
6
7
8
|
CSSearchableIndex.defaultSearchableIndex().deleteSearchableItemsWithDomainIdentifiers([«tv-shows»]) { (error) -> Void in
if error != nil {
print(error?.localizedDescription)
}
else {
// Items were deleted successfully
}
}
|
Создайте и запустите приложение еще раз. Когда вы пытаетесь найти любое из ваших шоу, результаты не возвращаются, потому что они были удалены из индекса.
3. Сочетание NSUserActivity
и основного внимания
Еще одно новое дополнение к классу NSUserActivity
в iOS 9 — это свойство contentAttributeSet
. Это свойство позволяет вам назначать CSSearchableItemAttributeSet
, как и те, что вы создали ранее. Этот набор атрибутов позволяет вашим результатам поиска для объектов NSUserActivity
отображать то же количество деталей, что и результаты поиска Core Spotlight.
Начните с добавления следующего импорта в начало файла DetailViewController.swift :
1
2
|
import CoreSpotlight
import MobileCoreServices
|
Затем обновите метод configureView
в классе DetailViewController
с помощью следующей реализации:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
func configureView() {
// Update the 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()
}
}
|
Создайте и запустите приложение в последний раз и откройте несколько своих шоу. Теперь, когда вы будете искать шоу, вы увидите, что ваши результаты, созданные с помощью NSUserActivity
, содержат тот же уровень детализации, что и результаты поиска Core Spotlight.
Вывод
Из этого руководства вы узнали, как сделать контент вашего приложения доступным через iOS Spotlight с помощью класса NSUserActivity
и платформы Core Spotlight . Я также показал вам, как индексировать контент из вашего приложения с помощью обоих API и как восстанавливать состояние вашего приложения, когда пользователь выбирает результат поиска.
Новые API поиска, представленные в iOS 9, очень просты в использовании и делают контент вашего приложения более простым для поиска и более доступным для пользователей вашего приложения. Как всегда, если у вас есть какие-либо комментарии или вопросы, оставьте их в комментариях ниже.