为开发者揭开 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: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 正在构建的公共索引相关的技术。 该索引旨在允许用户在您的应用中查找内容,即使它没有安装在他们的手机上。 我们将在下一篇文章中解决这个问题。