Objective-C中的Spotlight搜索与Siri集成
一、Spotlight 搜索基础
在 iOS 应用开发中,Spotlight 搜索为用户提供了一种便捷的方式,能够在设备上快速查找应用内的内容。Objective - C 作为 iOS 开发的传统语言,对 Spotlight 搜索有着良好的支持。
1.1 创建索引
为了让应用内容能够被 Spotlight 搜索到,首先需要创建索引。在 Objective - C 中,可以使用 CSSearchableIndex
类来完成这一操作。以下是创建索引的基本步骤:
- 导入框架:首先要导入
CoreSpotlight
框架,因为CSSearchableIndex
类在该框架中。
#import <CoreSpotlight/CoreSpotlight.h>
- 获取索引实例:通过
defaultSearchableIndex
类方法获取CSSearchableIndex
的单例实例。
CSSearchableIndex *searchableIndex = [CSSearchableIndex defaultSearchableIndex];
- 定义搜索项:创建
CSSearchableItemAttributeSet
对象,用于描述要索引的内容属性。例如,如果要索引一篇文章,可能会设置文章标题、摘要、作者等属性。
CSSearchableItemAttributeSet *attributeSet = [[CSSearchableItemAttributeSet alloc] initWithItemContentType:(NSString *)kUTTypeText];
attributeSet.title = @"示例文章标题";
attributeSet.contentDescription = @"这是一篇示例文章的摘要";
attributeSet.keywords = @[@"文章", @"示例"];
这里的 itemContentType
是用于指定内容类型的统一类型标识符(UTI)。常见的 UTI 如 kUTTypeText
表示文本,kUTTypeImage
表示图片等。
- 创建搜索项:使用
CSSearchableItem
类创建具体的搜索项,将CSSearchableItemAttributeSet
对象传入。
CSSearchableItem *searchableItem = [[CSSearchableItem alloc] initWithUniqueIdentifier:@"article1" domainIdentifier:@"com.example.app" attributeSet:attributeSet];
uniqueIdentifier
是该项的唯一标识符,domainIdentifier
一般设置为应用的 bundle ID,用于标识应用域。
- 添加搜索项到索引:最后将搜索项添加到索引中。
[searchableIndex indexSearchableItems:@[searchableItem] completionHandler:^(NSError * _Nullable error) {
if (error) {
NSLog(@"索引添加失败: %@", error);
} else {
NSLog(@"索引添加成功");
}
}];
在实际应用中,可能会有多个搜索项,只需将多个 CSSearchableItem
对象放入数组中传入 indexSearchableItems:completionHandler:
方法即可。
1.2 处理搜索结果
当用户在 Spotlight 中搜索应用相关内容并点击结果时,应用需要能够正确处理并展示对应的内容。在应用的 AppDelegate
中,可以通过实现 application:continueUserActivity:restorationHandler:
方法来处理搜索结果。
- 判断活动类型:首先要判断
userActivity
的类型是否为CSSearchableItemActionType
,这表示该活动是由 Spotlight 搜索结果触发的。
- (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void (^)(NSArray<id<UIUserActivityRestoring>> * _Nullable))restorationHandler {
if ([userActivity.activityType isEqualToString:CSSearchableItemActionType]) {
// 处理搜索结果
}
return YES;
}
- 获取搜索项标识符:从
userActivity
中获取搜索项的唯一标识符。
NSString *uniqueIdentifier = userActivity.userInfo[CSSearchableItemActivityIdentifier];
- 根据标识符加载内容:应用根据这个唯一标识符,从数据存储中加载对应的内容,并展示给用户。例如,如果是文章,可能会跳转到文章详情页面。
// 假设这里有一个方法根据标识符加载文章
Article *article = [Article loadArticleWithUniqueIdentifier:uniqueIdentifier];
if (article) {
ArticleViewController *articleVC = [[ArticleViewController alloc] initWithArticle:article];
UINavigationController *navController = (UINavigationController *)self.window.rootViewController;
[navController pushViewController:articleVC animated:YES];
}
二、Siri 集成基础
Siri 作为 iOS 设备上的智能语音助手,为应用提供了语音交互的能力。Objective - C 开发者可以通过 SiriKit 框架来实现应用与 Siri 的集成。
2.1 创建 Intents 扩展
要让应用支持 Siri 交互,首先需要创建一个 Intents 扩展。
-
创建新目标:在 Xcode 中,选择项目导航器中的项目,点击“File” -> “New” -> “Target”。在弹出的窗口中,选择“Intents Extension”,然后点击“Next”。按照提示设置扩展的名称、组织标识符等信息,最后点击“Finish”。
-
配置 Intents:在 Intents 扩展的
IntentsDefinitionFile.intentdefinition
文件中,定义应用支持的意图(Intent)。例如,如果应用是一个待办事项应用,可以定义“添加待办事项”、“完成待办事项”等意图。 -
实现 Intent 处理逻辑:在 Intents 扩展的
IntentHandler.m
文件中,实现定义的意图处理逻辑。以“添加待办事项”意图为例,假设意图名为AddTodoIntent
。
#import "IntentHandler.h"
#import "AddTodoIntent.h"
@interface IntentHandler () <AddTodoIntentHandling>
@end
@implementation IntentHandler
- (id <AddTodoIntentHandling>)handlerForAddTodoIntent:(AddTodoIntent *)intent {
return self;
}
- (void)handleAddTodoIntent:(AddTodoIntent *)intent completion:(void (^)(AddTodoIntentResponse *response))completion {
// 解析意图参数
NSString *todoTitle = intent.todoTitle;
// 调用应用逻辑添加待办事项
BOOL success = [TodoManager addTodoWithTitle:todoTitle];
if (success) {
AddTodoIntentResponse *response = [[AddTodoIntentResponse alloc] initWithCode:AddTodoIntentResponseCodeSuccess userActivity:nil];
response.title = @"待办事项已添加";
completion(response);
} else {
AddTodoIntentResponse *response = [[AddTodoIntentResponse alloc] initWithCode:AddTodoIntentResponseCodeFailure userActivity:nil];
response.title = @"添加待办事项失败";
completion(response);
}
}
@end
这里的 TodoManager
是一个假设的用于管理待办事项的类,addTodoWithTitle:
方法负责实际的添加逻辑。
2.2 配置应用以支持 Siri
在主应用中,还需要进行一些配置以支持 Siri。
-
添加权限:在应用的
Info.plist
文件中,添加NSPhotoLibraryUsageDescription
(如果应用需要访问相册等)、NSMicrophoneUsageDescription
(如果应用需要使用麦克风)等权限描述,以确保 Siri 集成时权限合规。 -
关联 Intents 扩展:在主应用的
Info.plist
文件中,添加NSExtensionAttributes
字典,并在其中设置IntentsSupported
数组,列出应用支持的意图。例如:
<key>NSExtensionAttributes</key>
<dict>
<key>IntentsSupported</key>
<array>
<string>AddTodoIntent</string>
</array>
</dict>
- 测试 Siri 集成:在设备上安装应用及其 Intents 扩展后,可以通过长按 Home 键(或使用 iPhone X 及后续机型的侧边按钮)唤起 Siri,并说出与定义的意图相关的语音指令,如“在[应用名称]中添加待办事项[具体事项]”,测试应用与 Siri 的集成是否正常。
三、Objective - C 中 Spotlight 搜索与 Siri 集成的结合
将 Spotlight 搜索与 Siri 集成结合,可以为用户提供更加无缝的搜索和交互体验。
3.1 利用 Siri 触发 Spotlight 搜索相关操作
假设应用中已经通过 Spotlight 索引了一些内容,并且通过 Siri 可以触发与这些内容相关的操作。例如,用户可以通过 Siri 搜索应用内的文章,并直接跳转到文章详情页面。
-
修改 Intents 定义:在 Intents 扩展的
IntentsDefinitionFile.intentdefinition
文件中,定义一个新的意图,比如SearchArticleIntent
,用于搜索文章。为该意图添加参数,如文章关键词。 -
实现意图处理逻辑:在
IntentHandler.m
文件中实现SearchArticleIntent
的处理逻辑。
#import "IntentHandler.h"
#import "SearchArticleIntent.h"
@interface IntentHandler () <SearchArticleIntentHandling>
@end
@implementation IntentHandler
- (id <SearchArticleIntentHandling>)handlerForSearchArticleIntent:(SearchArticleIntent *)intent {
return self;
}
- (void)handleSearchArticleIntent:(SearchArticleIntent *)intent completion:(void (^)(SearchArticleIntentResponse *response))completion {
NSString *keyword = intent.keyword;
// 模拟根据关键词搜索文章的逻辑,这里假设返回一个文章标识符数组
NSArray<NSString *> *articleIdentifiers = [ArticleSearcher searchArticlesWithKeyword:keyword];
if (articleIdentifiers.count > 0) {
// 这里简单取第一个文章标识符作为示例
NSString *articleIdentifier = articleIdentifiers[0];
CSSearchableItemAttributeSet *attributeSet = [[CSSearchableItemAttributeSet alloc] initWithItemContentType:(NSString *)kUTTypeText];
attributeSet.title = @"搜索到的文章标题";
attributeSet.contentDescription = @"搜索到的文章摘要";
CSSearchableItem *searchableItem = [[CSSearchableItem alloc] initWithUniqueIdentifier:articleIdentifier domainIdentifier:@"com.example.app" attributeSet:attributeSet];
[CSSearchableIndex.defaultSearchableIndex indexSearchableItems:@[searchableItem] completionHandler:^(NSError * _Nullable error) {
if (error) {
SearchArticleIntentResponse *response = [[SearchArticleIntentResponse alloc] initWithCode:SearchArticleIntentResponseCodeFailure userActivity:nil];
response.title = @"搜索失败";
completion(response);
} else {
// 模拟跳转到文章详情的操作,这里返回成功响应
SearchArticleIntentResponse *response = [[SearchArticleIntentResponse alloc] initWithCode:SearchArticleIntentResponseCodeSuccess userActivity:nil];
response.title = @"搜索成功,即将跳转到文章";
completion(response);
}
}];
} else {
SearchArticleIntentResponse *response = [[SearchArticleIntentResponse alloc] initWithCode:SearchArticleIntentResponseCodeFailure userActivity:nil];
response.title = @"未找到相关文章";
completion(response);
}
}
@end
这里的 ArticleSearcher
是一个假设的用于搜索文章的类,searchArticlesWithKeyword:
方法根据关键词搜索文章并返回文章标识符数组。
- 在主应用中处理结果:当用户通过 Siri 触发
SearchArticleIntent
并成功搜索到文章后,在主应用的application:continueUserActivity:restorationHandler:
方法中处理搜索结果,跳转到文章详情页面,与处理 Spotlight 搜索结果类似。
- (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void (^)(NSArray<id<UIUserActivityRestoring>> * _Nullable))restorationHandler {
if ([userActivity.activityType isEqualToString:CSSearchableItemActionType]) {
NSString *uniqueIdentifier = userActivity.userInfo[CSSearchableItemActivityIdentifier];
Article *article = [Article loadArticleWithUniqueIdentifier:uniqueIdentifier];
if (article) {
ArticleViewController *articleVC = [[ArticleViewController alloc] initWithArticle:article];
UINavigationController *navController = (UINavigationController *)self.window.rootViewController;
[navController pushViewController:articleVC animated:YES];
}
}
return YES;
}
3.2 使用 Spotlight 搜索引导 Siri 交互
反过来,也可以利用 Spotlight 搜索的结果来引导用户进行 Siri 交互。例如,在 Spotlight 搜索结果中显示一些提示,告知用户可以通过 Siri 执行与该结果相关的进一步操作。
- 自定义搜索结果展示:在创建
CSSearchableItemAttributeSet
对象时,可以添加自定义属性来显示提示信息。
CSSearchableItemAttributeSet *attributeSet = [[CSSearchableItemAttributeSet alloc] initWithItemContentType:(NSString *)kUTTypeText];
attributeSet.title = @"示例文章标题";
attributeSet.contentDescription = @"这是一篇示例文章的摘要";
attributeSet.keywords = @[@"文章", @"示例"];
attributeSet.userInfo = @{@"siriHint": @"通过 Siri 朗读这篇文章"};
- 在搜索结果视图中展示提示:当应用处理 Spotlight 搜索结果并展示给用户时,从
CSSearchableItemAttributeSet
的userInfo
中取出siriHint
信息,并在界面上合适的位置展示给用户,引导用户通过 Siri 执行“朗读文章”等操作。在实际实现中,可能需要根据应用的界面布局,在搜索结果的单元格或详情页面等位置添加相应的提示标签。
四、优化与注意事项
在实现 Objective - C 中的 Spotlight 搜索与 Siri 集成时,有一些优化点和注意事项需要关注。
4.1 性能优化
- 索引优化:避免在主线程上进行大规模的索引操作,因为索引过程可能会比较耗时。可以使用
dispatch_async
将索引操作放到后台队列中执行。
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
CSSearchableIndex *searchableIndex = [CSSearchableIndex defaultSearchableIndex];
CSSearchableItemAttributeSet *attributeSet = [[CSSearchableItemAttributeSet alloc] initWithItemContentType:(NSString *)kUTTypeText];
attributeSet.title = @"示例文章标题";
attributeSet.contentDescription = @"这是一篇示例文章的摘要";
attributeSet.keywords = @[@"文章", @"示例"];
CSSearchableItem *searchableItem = [[CSSearchableItem alloc] initWithUniqueIdentifier:@"article1" domainIdentifier:@"com.example.app" attributeSet:attributeSet];
[searchableIndex indexSearchableItems:@[searchableItem] completionHandler:^(NSError * _Nullable error) {
if (error) {
NSLog(@"索引添加失败: %@", error);
} else {
NSLog(@"索引添加成功");
}
}];
});
- Siri 意图处理优化:在处理 Siri 意图时,尽量减少复杂的计算和网络请求。如果需要进行网络请求,可以使用异步请求,并在请求完成后返回合适的响应给 Siri。例如,使用
NSURLSession
进行异步网络请求:
- (void)handleSomeIntent:(SomeIntent *)intent completion:(void (^)(SomeIntentResponse *response))completion {
NSURL *url = [NSURL URLWithString:@"http://example.com/api/someapi"];
NSURLSessionDataTask *task = [[NSURLSession sharedSession] dataTaskWithURL:url completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
if (error) {
SomeIntentResponse *response = [[SomeIntentResponse alloc] initWithCode:SomeIntentResponseCodeFailure userActivity:nil];
response.title = @"请求失败";
dispatch_async(dispatch_get_main_queue(), ^{
completion(response);
});
} else {
// 解析数据并处理
// 返回成功响应
SomeIntentResponse *response = [[SomeIntentResponse alloc] initWithCode:SomeIntentResponseCodeSuccess userActivity:nil];
response.title = @"操作成功";
dispatch_async(dispatch_get_main_queue(), ^{
completion(response);
});
}
}];
[task resume];
}
4.2 兼容性与更新
- iOS 版本兼容性:确保应用支持的 iOS 版本能够正常使用 Spotlight 搜索和 Siri 集成功能。随着 iOS 版本的更新,可能会有新的特性和 API 变化,需要及时关注并适配。例如,在较新的 iOS 版本中,SiriKit 可能会有新的意图类型或增强的功能。
- 应用更新:当应用更新时,需要考虑对 Spotlight 搜索索引和 Siri 集成的影响。如果应用的数据结构或功能发生变化,可能需要更新索引内容和意图处理逻辑。可以在应用更新时,添加相应的迁移逻辑,如更新或重建 Spotlight 搜索索引。
4.3 用户体验优化
- 搜索结果相关性:确保 Spotlight 搜索结果与用户输入的关键词高度相关。这需要在创建索引时,合理设置关键词、标题和摘要等属性。同时,可以使用一些机器学习或自然语言处理技术(如果适用)来提高搜索的准确性。
- Siri 交互友好性:在 Siri 意图处理过程中,返回给用户的响应信息应该清晰、简洁且友好。避免使用过于技术化或难以理解的语言。例如,在处理“添加待办事项”意图时,如果添加成功,返回的响应可以是“已为您成功添加待办事项,快去看看吧!”而不是简单的“成功”。
通过以上对 Objective - C 中 Spotlight 搜索与 Siri 集成的深入探讨,开发者可以为应用添加强大的搜索和语音交互功能,提升用户体验,使应用在众多 iOS 应用中脱颖而出。在实际开发过程中,需要根据应用的具体需求和业务逻辑,灵活运用这些技术,并不断优化和完善。