[iOS] Core Spotlight

naljin
8 min readAug 25, 2019

--

App content를 인덱싱 하기

  1. import CoreSpotlight
  2. CSSearchableItemAttributeSet 객체를 적절한 itemContentType 과 함께 생성 및 초기화.
  • attributeSet이란 검색결과에 나타날 메타데이터를 특정하는 속성의 집합.
  • 이때 itemContentType은 kUTTypePNGkUTTypeMovie 과 같은 콘텐츠의 uniform type identifier이고, 이를 위해서 MobileCoreServices 임포트 필요
import MobileCoreServices

3. 인덱스하려는 아이템에 대한 속성을 설정. 다음과 같은 속성들을 통해 Spotlight에서 검색 시 나타날 값을 지정할 수 있음

  • title : 검색 결과에서 메인으로 표시될 값
  • contentDescription : 아이템 콘텐츠 설명. 검색 결과에서 title 밑에 부가적으로 뜨는 값
  • thumbnailData : 검색 결과에서 섬네일로 뜨게 될 데이터

4. 아이템을 나타내는 CSSearchableItem 객체 생성. 해당 객체에 대해 참조 가능한 unique identifier 가짐. 만약 NULL로 설정하면 자동으로 할당됨

5. 필요하다면 domain identifier 설정을 통해 다수의 아이템들을 그룹으로 묶어 한번에 관리할 수 있게 함

  • domain identifier란 아이템의 domain이나 owner을 표시하는 식별자(optional). album 등과 같이 표기함으로써 아이템들을 그룹화할 수 있음.
  • 계정이 삭제될 때 관련된 아이템들도 모두 삭제 되기를 원하는 어떤 메일 박스(e.g. naver)가 있을때, domain 식별자는 account-id.mailbox-id 형식이 되어야함. 이때 각각은 온점을 포함하면 안되며 deleteSearchableItems(withDomainIdentifiers:completionHandler:) 를 호출해서 첫번째 파라미터로 전달하면 됨. 아니면, 계정이 삭제될 때 그와 관련된 모든 메일박스(e.g. naver, gmail ..) 아이템을 지우고 싶으면 account-id를 인자로 넘기는 방식으로 해결할 수 있음.

6. attributeset 과 searchable item 을 관련지음(associate)

7. CSSearchableIndex에 searchable item 추가. CSSearchableIndex는 Spotlight에 indexing 되는 콘텐츠와 관련이 있는 클래스. CSSearchableItem의 배열 요구.

Searchable item 삭제하기 (세가지 방법 존재)

  1. index로 부터 모든 searchable item 삭제
func deleteAllSearchableItems(completionHandler: ((Error?) -> Void)?)

2. 특정 identifier를 지정해서 index로 부터 해당 searchable item 삭제

func deleteSearchableItems(withIdentifiers: [String], completionHandler: ((Error?) -> Void)?)

3. 특정 domain을 지정해서 index로 부터 관련된 searchable item 삭제

func deleteSearchableItems(withDomainIdentifiers: [String], completionHandler: ((Error?) -> Void)?)

Searchable item 수정하기

업데이트를 원하는 아이템의 unique identifier와 함께 CSSearchableItem 객체를 새로 생성하고 아이템을 인덱싱할 때 사용했던 동일한 메소드를 호출.

<예시 코드>

//생성 및 수정
func indexSearchableItems(selectedItem : MySearchableItem){
// 아이템 설명하는 속성 생성
let attributeSet = CSSearchableItemAttributeSet(itemContentType: kUTTypeData as String)
// 아이템에 대한 디테일 보충하는 metadata 추가
attributeSet.title = selectedItem.title
attributeSet.contentDescription = selectedItem.desc
// unique identifier, domain identifier 그리고 위에서 만든 attribute set과 함께 생성
let item = CSSearchableItem(uniqueIdentifier: selectedItem
.uniqueId, domainIdentifier: selectedItem.type.rawValue, attributeSet: attributeSet)
// on-device index에 item 추가.
CSSearchableIndex.default().indexSearchableItems([item]) { error in
print(error != nil ? error?.localizedDescription ?? "" : "item indexed")
}
}

//특정 아이템 삭제
func deleteSearchableItems(uniqueId : String){
//삭제할때 연관되어있는 identifier 설정 통해서 지우는 것
CSSearchableIndex.default().deleteSearchableItems(withIdentifiers: [uniqueId]) { error in
print(error != nil ? error?.localizedDescription ?? "" : "item deleted")
}
}

//전체 아이템 삭제
func deleteAllSearchableItems(){
CSSearchableIndex.default().deleteAllSearchableItems { error in
print(error != nil ? error?.localizedDescription ?? "" : "all item deleted")
}
}

사용자 응답

유저가 Spotlight 검색 결과에서 indexed item 을 탭하면 app delegate의 application:continueUserActivity:restorationHandler: 함수 호출 (위의 NSUserActivity와 동일). 이 상황에서 app delegate가 받는 activity type은 CSSearchableItemActionType 이고 해당 type을 기준으로 app content 보여줄건지 말건지 판단하면 됨.

<예시 코드>

func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool {
if userActivity.activityType == CSSearchableItemActionType {
//Core Spotlight
if let uniqueIdentifier = userActivity.userInfo?[CSSearchableItemActivityIdentifier] as? String {
//CSSearchableItemActivityIdentifier를 키값으로해서 uniqueIdentifier 찾을 수 있음
//필요한 동작 수행
}
} else {
//NSUserActivity
}
return true
}

Reference

공식문서

Apple Developer Documentation — Core Spotlight

Apple Developer Documentation — NSUserActivity

Apple Developer Documentation — WKNavigationDelegate

Apple Developer Documentation — App Search Programming Guide

2015 WWDC — Search API

Apple Developer — Search

기타 참고 사이트

[민소네]Search API를 사용해보자

[Zeddios]Task Management

NSUSERACTIVITY TUTORIAL HOW TO USE IOS 10 SEARCH API

iOS9과 앱 인덱싱

iOS 10 Spotlight App Discovery: NSUserActivity and Search Relevancy

[Stack over Flow]NSUserActivity와 Core Spotlight의 차이

iOS 9 App Search Tutorial: Introduction to App Search

Core Spotlight 구현 방법

How to use Core Spotlight to index content in your app

--

--

No responses yet