我正在尝试在应用程序中使用CoreSpotlight。我已经设置了数据类来创建可在iOS中与Spotlight一起使用的CSSearchableItems,但是在应用程序内,由于我们希望将其用于搜索结果,因此我需要每个结果的更多信息。我一直在尝试创建与我需要的信息相对应的CSCustomAttributeKeys,它们在某种程度上可以正常工作。我能够检索它们直到它们进入索引-然后,当我使用CSSearchQuery将它们拉回时,它们的格式不同,无法再访问。
我在这里查看了这个问题:How to get custom value back from Spotlight with CSCustomAttributeKey
答案表明这是一个iOS错误。我希望现在已解决此问题,但找不到任何验证。
我也阅读了多次文档,但是关于如何进行设置的信息很少(除非我遗漏了一些东西)。
CSCustomAttributeKey类定义了可以关联的键 具有可搜索项的自定义属性。项目属性提供 有关可以在其中索引并显示给用户的项目的元数据 搜索结果。尽管Core Spotlight框架提供了一些 预定义的属性(例如标题和说明),您可以创建一个 CSCustomAttributeKey对象,用于指定使 在您的域中有意义。
您选择的属性取决于您的域。您可以使用 Spotlight在以下定义的类别中提供的属性 CSSearchableItemAttributeSet(例如媒体和文档),也可以 定义自己的。如果要定义自定义属性,请按照 在定义中尽可能具体,并使用contentTypeTree 属性,以便您的自定义属性可以从已知类型继承。
来源:https://developer.apple.com/documentation/corespotlight/cssearchableitemattributeset?language=objc
我的假设是,这里最重要的一行是我需要设置contentTypeTree-但是,我不了解此属性的用途或用法:
一种属性类型,用于标识要定义的类型的自定义层次结构 描述您商品的属性。
...
例如,contentType为的项目的contentTypeTree public.m3u播放列表应包括public.m3u播放列表和 public.playlist。
let attributeSet = CSSearchableItemAttributeSet(itemContentType: kUTTypeData as String)
attributeSet.title = title
attributeSet.contentDescription = description
attributeSet.keywords = keywords
attributeSet.setValue("5" as NSString, forCustomKey: "com_fake_test"!)
let item = CSSearchableItem(uniqueIdentifier: url, domainIdentifier: "com_fake", attributeSet: attributeSet)
// printing attributeSet here shows the custom attribute as separate from other attributes
CSSearchableIndex.default().indexSearchableItems([item]) { error in
if let error = error {
print("Indexing error: \(error.localizedDescription)")
} else {
print("Search item successfully indexed!")
}
}
// separate class, searchQuery is a global CSSearchQuery object and allItems is a global [CSSearchableItem] object
searchQuery?.cancel()
searchQuery = CSSearchQuery(queryString: spotlightQueryString(fromQueryString: curSearchStr!), attributes: ["com_fake_test"])
searchQuery?.foundItemsHandler = { (items: [CSSearchableItem]) in
self.allItems.append(contentsOf: items)
}
searchQuery?.completionHandler = { (error) in
guard error == nil else {
print("Error: \(error?.localizedDescription)")
return
}
DispatchQueue.main.async {
for item in self.allItems {
var attributes = item.attributeSet
// this will be nil!
var extractedAttribute = item.attributeSet.value(forCustomKey: IndexItemFactory.SUBSTANCE_ATTRIBUTE!)
}
self.searchComplete(SearchMultiResults(searchStr: self.curSearchStr!, substanceResults: substanceResults))
}
}
searchQuery?.start()
首次检查属性(在索引编制之前):
"Printing description of attributes:
{
"_kMDItemDomainIdentifier" = "come.fake.test";
"_kMDItemExpirationDate" = "2019-07-08 00:00:00 +0000";
"_kMDItemExternalID" = "fakeID";
kMDItemContentType = "public.data";
kMDItemDescription = "fake description";
kMDItemKeywords = (
"keyword1",
"keyword2",
"keyword3"
);
kMDItemTitle = "fakeTitle";
}
Custom:
{
"<CSCustomAttributeKey:0x6000024cfee0 com_fake_test" = 5;
}"
第二次时间检查属性(在索引编制之后):
"Printing description of attributes:
{
"_kMDItemBundleID" = "com.fake";
"_kMDItemDomainIdentifier" = "com.fake";
"_kMDItemExpirationDate" = "2019-07-08 00:00:00 +0000";
"_kMDItemExternalID" = "fakeID";
"com_fake_test" = 5;
}"