為開發者揭開 iOS 9 Spotlight 搜索的神秘面紗
已發表: 2022-03-11iOS 內置了三個搜索點:Siri、Spotlight 搜索和 Safari 搜索。 Siri 是 iOS 最具標誌性的功能之一,是大多數 iPhone 用戶已經熟悉的功能。 但很多人並不知道 Spotlight 搜索——早在 Siri 出現之前,它就已成為 iOS 不可或缺的一部分。 Spotlight Search 可以在您向下滑動主屏幕時訪問,或者對於 iOS 9 的新用戶,從您的個人主屏幕向右滑動即可訪問。 這會在屏幕頂部顯示一個搜索欄。
iOS 8 及更早版本中此搜索工具的重點是搜索手機本身,因此其結果頁面會列出您手機上的應用程序,以及 Apple 應用程序中的電子郵件、消息和其他私人項目。 如果看起來相關,它還將顯示 Wikipedia 定義。 最後,它提供了一個通過 Safari 搜索網絡的選項作為附加步驟。
與 Spotlight Search 相比,Safari 是關於手機之外的世界。 在 iOS 8 中,用戶可以選擇用於 Safari 搜索的搜索引擎:Google、Yahoo、Bing 和 DuckDuckGo。 谷歌自然會處理大部分 Safari 搜索請求。 無論選擇哪種搜索引擎,Safari 中都會顯示預填充的搜索詞,可能與 Wikipedia 匹配。
在 iOS 9 中,Spotlight Search 比以前更加突出和範圍更廣。 事實上,您首先看到的是基於您的使用模式的“Siri 建議”。 例如,如果你經常在下午使用 Safari,Siri 會在那個時間左右為你推薦它。
而且,雖然它仍然是一個查找“手機上的東西”的地方,但它正在成為“手機上的東西”的直接門戶。 您已經通過 Apple 自己的搜索引擎看到了附近的事物和來自網絡的新聞頭條,而其他基於網絡的結果現在才剛剛開始出現。
是的,Apple 為 iOS 9 創建了一個網絡搜索引擎,這是非常大的一步。 向 Applebot 打個招呼。
與 Spotlight 類似,Apple 對 Safari 的既定目標也是從 Apple 的搜索索引中顯示結果和建議,然後提供使用 Google(或其他選擇的提供商)搜索網絡的能力。 從 iOS 9.1 開始,Safari 似乎落後於 Spotlight 搜索,因為它繼續提供來自用戶選擇的搜索提供商的結果——也許是為了讓 Apple 更慢地推出其搜索功能並有更多時間來微調其算法。
iOS 9 的發布特別令人興奮的是,它首次讓 iOS 開發人員能夠連接到這些搜索功能並包含來自應用程序的內容。 此外,承諾是搜索最終將包括不在用戶手機上的結果。 這是一大步。
讓我們把它放到上下文中。 Google 的搜索引擎催生了一個圍繞“SEO”構建的整個行業——圍繞 Google 搜索優化您的資產的過程。 全面推出後,Apple 的搜索引擎將擁有大約 50% 的移動搜索市場,佔總搜索流量的 50%(並且還在增長)。 Applebot 因此很大,這意味著“Apple 移動搜索優化”也將很大。
Apple 移動搜索優化工作將對移動用戶的應用發現產生比常規 SEO 更大的影響。
歡迎來到新生的 AMSO 行業。
壞消息是,實現所有這些功能涉及 Apple 的許多新技術以及對舊技術的增強,這些元素的組合可能會令人困惑。 本系列的目標是瀏覽各個部分並闡明如何實現它們。 讓我們從一些基本的東西開始,並以此為基礎。
為了支持這個系列,我創建了一個簡單的應用程序供整個參考。 該項目可以在這裡找到:https://github.com/rwforsythe/iOS9-Search。 隨著本系列繼續涵蓋搜索工具包的其他元素,它也將被更新。
基礎:CoreSpotlight 框架
這個框架在 iOS 9 中是全新的,允許您將項目添加到 iPhone 的本地搜索索引中,以供用戶發現。 例如,在 iOS 9 之前,只能通過 Spotlight 搜索找到 Apple 官方應用程序中的內容,例如日曆。 現在,任何通過 CoreSpotlight 框架發布其日曆事件的應用程序都可以通過 Spotlight Search 甚至 Siri 找到。
請注意,這裡的重點是個人信息; 您不希望用戶在另一部手機上找到您的個人日曆活動! Apple 非常清楚,CoreSpotlight 框架只與每個人手機上的私有索引進行交互。 無法使用 CoreSpotlight API 發布手機自身索引之外的內容。
這並不意味著 CoreSpotlight 不能用於索引已經公開的信息。 當然可以使用 CoreSpotlight 從雲中提取信息並將其放入手機的搜索索引中。 這只是 Apple 的保證,如果個人和機密信息被 CoreSpotlight 索引,它將保持機密。
該框架分為兩部分:允許應用詳細描述每個項目的CSSearchableItemAttributeSet對象,以及用於為項目提供唯一 ID 的CSSearchableItem對象。 每個 Spotlight 條目都由一對這樣的對象組成。 使用兩個對象而不是一個對象的原因是CSSearchableItemAttributeSet對像用於不同類型的搜索交互(稍後描述)。
做基礎很容易。
對於那些引用示例代碼的人,CoreSpotlight 的設置是在 AppDelegate 中完成的。
… @import CoreSpotlight; @import MobileCoreServices; …
新功能需要這兩個模塊。
為了簡化演示應用程序,應用程序:didFinishLaunchingWithOptions:方法用於調用專用方法來設置 CoreSpotlight:
if ([CSSearchableItemAttributeSet class]) [self setUpCoreSpotlight]; //Check for iOS version that supports CoreSpotlight API
向下移動到setUpCoreSpotlight方法,我們通過創建一個CSSearchableItemAttributeSet對象來啟動該過程:
CSSearchableItemAttributeSet * attributeSet = [[CSSearchableItemAttributeSet alloc] initWithItemContentType:(NSString *)kUTTypeItem];
內容類型很重要,因為它應該控制搜索算法處理項目的一般方式。 “假定”是一個有效的詞,因為這是一個蘋果沒有很好地記錄的領域。 有大量項目類型可供選擇(圖像類型、視頻類型、音頻類型、聯繫人類型),但需要反複試驗才能確定它對用戶體驗的影響(如果有的話)。 在搜索結果中顯示時,某些類型似乎比其他類型顯示更多的文本內容。 它還會影響縮略圖是否與結果一起顯示。 kUTTypeItem 是一個很好的起點。
現在更詳細地描述該對象:
attributeSet.displayName = @"A Christmas Carol"; attributeSet.title = @"A Christmas Carol By Charles Dickens"; //Sounds similar to displayName but is not displayed to user attributeSet.contentDescription = @"Who would dare to say “Bah! Humbug” after reading A Christmas Carol? Charles Dickens wrote the novella in just six weeks before it was first published on December 19 1843 but his morality tale about a bitter old miser named Ebenezer Scrooge lives on to this day as a reminder of the importance of the Christmas spirit."; attributeSet.keywords = @[@"A Christmas Carol", @"Charles Dickens", @"Victorian Literature"]; UIImage *image = [UIImage imageNamed:@"CC-Cover"]; NSData *imageData = [NSData dataWithData:UIImagePNGRepresentation(image)]; attributeSet.thumbnailData = imageData;
有很多可能的屬性,特定於圖像、視頻等媒體類型。 更多信息可能更好,但需要反複試驗來確定實際使用和/或顯示在搜索結果中的信息。 例如,在撰寫本文時,似乎沒有顯示給定索引項的星級,即使 attributeSet 包含星級數據。

大多數文本屬性都包含在搜索查詢中,因此即使不顯示標題屬性,也可以通過搜索找到文本。 因此,不完全清楚關鍵字屬性與標題屬性有何根本不同。
有關更多信息,請參閱 Apple 文檔:developer.apple.com
最後一步是將CSSearchableItemAttributeSet與CSSearchableItem 打包並註冊到索引中。
CSSearchableItem *item1 = [[CSSearchableItem alloc] initWithUniqueIdentifier:@”https://www.notestream.com/streams/564159e4e5c24” domainIdentifier:@"notestream.com" attributeSet:attributeSet];
這裡有兩個新東西。 domainIdentifier屬性允許您將項目組合在一起以進行批處理操作。 例如,日曆應用程序中的@“meetingItem”和@“reminderItem”將允許您刪除一種類型的所有 Spotlight 條目,同時保留另一種。
uniqueIdentifier屬性扮演著更重要的角色。 首先,當用戶單擊 CoreSpotlight 索引中的項目時,它會被傳回您的應用程序(稍後討論)。 其次,Apple 提出了關於在使用搜索基礎設施的其他元素時應該是什麼樣子的建議。 現在,我們將使用一個字符串,它實際上是一個唯一代表該項目的 URL。 從技術上講,這個屬性可以是任何字符串,只要它對項目是唯一的。
最後一步:將您創建的項目推送到實際索引中。
[[CSSearchableIndex defaultSearchableIndex] indexSearchableItems:@[item1, item2, item3] completionHandler: ^(NSError * __nullable error) { if (!error) NSLog(@"Search item(s) journaled for indexing."); }];
這裡需要說明幾點:
這個方法接受一個對像數組(如果有很多數據要索引,還有其他方法可以用來批處理這個過程)。
重要的是要意識到這種方法實際上並沒有完成索引過程。 只有當您的搜索項已排隊等待索引時,才會調用完成處理程序。 使用CSSearchableIndexDelegate處理索引過程本身由於某種原因失敗並且您的應用程序需要處理這種情況的情況。
恭喜,您已將項目添加到手機的 CoreSpotlight 搜索索引!
iOS 9 中搜索的工作原理
當然,Apple 將他們的搜索算法放在胸前,因此安裝示例應用程序並使用關鍵字是值得的。 例如,很明顯,Apple 通過在用戶鍵入每個字母時給出非常不同的結果來最大化呈現的結果:
看起來原理是,只要輸入幾個字母,就會顯示認為更合適的結果。 隨著用戶輸入更多的字母,那些早期的結果會被丟棄,而會出現其他的東西(最初估計不太可能)。
更一般地說,關於如何在他們的算法下提高排名,蘋果只有幾句話要說。 此頁麵包含 Apple 的建議:增強您的搜索結果
Apple 文檔的主要內容之一是,當應用程序使用多種搜索技術來索引內容時,排名會提高。 我們將在下一篇文章中深入探討其中的另一種技術。 同時,我們還需要實現代碼來處理用戶點擊搜索結果的場景。
當用戶點擊
我們已經創建了代碼來使用潛在的搜索結果填充索引,但是當用戶單擊結果時會發生什麼? 答案是 CoreSpotlight 從 UIApplicationDelegate 協議中藉用了 application application:continueUserActivity:restorationHandler:
方法。 這最初是在 iOS 8 中引入的,用於允許用戶活動從設備傳遞到設備的切換機制(例如,用戶在 iWatch 上看到 Web URL,使用切換在 iPhone Safari 瀏覽器上獲取它,並最終查看它當他們到達辦公室時在他們的 Mac 上。)
第一個挑戰是確定該方法是否由於切換活動或 Spotlight 搜索而被調用。 activity 參數的 activityType 屬性會告訴你,但如果代碼可能在 iOS 8 上運行,你需要避免在這種情況下崩潰。
以下是一些簡單代碼的外觀:
- (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)activity restorationHandler:(void (^)(NSArray *))restorationHandler { NSString * valueCSSearchableItemActionType; BOOL wasHandled = NO; if ([CSSearchableItemAttributeSet class]) //iOS 9 { valueCSSearchableItemActionType = CSSearchableItemActionType; } else { // iOS 8 – This method was introduced in iOS 8, so iOS 7 is not a possible scenario valueCSSearchableItemActionType = @"not supported"; } if ([activity.activityType isEqual: valueCSSearchableItemActionType]) { // Invoked via CoreSpotlight, we can assume iOS 9 from now on… NSString * activityIdentifier = [activity.userInfo valueForKey:CSSearchableItemActivityIdentifier]; wasHandled = YES; NSLog(@"Continuing user activity %@", activityIdentifier); } else { //the app was launched via Handoff protocol //or with a Universal Link } return wasHandled; }
注意代碼行:
NSString * activityIdentifier = [activity.userInfo valueForKey:CSSearchableItemActivityIdentifier];
這會提取在創建CSSearchableItem對象時放置在聚光燈索引中的唯一標識符。 自然,您的應用程序應該使用此唯一標識符向用戶展示他們從搜索索引中選擇的內容。 這里為了簡單起見,我們只是 NSLog 唯一標識符。
回顧
到目前為止,我們只研究了 iOS 9 搜索功能的一部分。 我們已經完成了加載手機的 Spotlight 搜索索引所需的核心功能,其中包含用戶可能認為有用的內容:文檔、日曆項目、聯繫人等。 當用戶搜索某些內容、看到您的應用程序的結果並單擊它時,應用程序將能夠處理請求並為用戶顯示適當的項目。
我們尚未討論的是與 Apple 正在構建的公共索引相關的技術。 該索引旨在允許用戶在您的應用中查找內容,即使它沒有安裝在他們的手機上。 我們將在下一篇文章中解決這個問題。