How to get custom value back from Spotlight with CSCustomAttributeKey

时光总嘲笑我的痴心妄想 提交于 2019-12-22 05:19:30

问题


I am trying to get some data back from Core Spotlight which I am storing using a custom attribute key. Tested this on macOS and iOS as well, the result is always the same.

My test class:

import CoreSpotlight

class SpotlightSearch {
  let domainId = "com.company.some"
  let originalDataKeyName: String

  init() {
    self.originalDataKeyName = domainId.replacingOccurrences(of: ".", with: "_") + "_originalData"
  }

  func addToIndex(title: String, content: String) {
    guard let originalDataKey = CSCustomAttributeKey(keyName: originalDataKeyName, searchable: false, searchableByDefault: false, unique: false, multiValued: false)

      else { return }

    let uniqueId = "MyUniqueId" + title
    let originalContent = NSString(string: content)

    let attributeSet = CSSearchableItemAttributeSet(itemContentType: kUTTypeText as String)
    attributeSet.title = title
    attributeSet.setValue(originalContent, forCustomKey: originalDataKey)
    let item = CSSearchableItem(uniqueIdentifier: uniqueId, domainIdentifier: domainId, attributeSet: attributeSet)
    CSSearchableIndex.default().indexSearchableItems([item]) { error in
      if let error = error {
        print("Indexing error: \(error.localizedDescription)")
      } else {
        print("Item '\(title)' successfully indexed!")
      }
    }
  }

  var query: CSSearchQuery?

  func search(title: String) {
    var allItems = [CSSearchableItem]()
    let queryString = "title == '\(title)'cd"
    let attributes = [ "title", originalDataKeyName ]
    let newQuery = CSSearchQuery(queryString: queryString, attributes: attributes)
    newQuery.foundItemsHandler = { (items: [CSSearchableItem]) -> Void in
      allItems.append(contentsOf: items)
    }

    newQuery.completionHandler = { [weak self] (error: Error?) -> Void in
      guard let originalDataKeyName = self?.originalDataKeyName,
            let originalDataKey = CSCustomAttributeKey(keyName: originalDataKeyName)
       else { return }
      print("Search complete")
      for item in allItems {
        let attributeSet = item.attributeSet
        let customData = attributeSet.value(forCustomKey: originalDataKey)
        // Always nil
        if customData == nil {
          print("\(String(describing: originalDataKeyName)) not found in \(attributeSet.description)")
        } else if let originalData = customData as? NSData {
          let data = Data(referencing: originalData)

          if let originalString = String(data: data, encoding: .utf8) {
            print("Found '\(originalString)'")
          }
        }
      }
    }
    query = newQuery
    newQuery.start()
  }
}

On app init:

let newSpotlightSearch = SpotlightSearch()
newSpotlightSearch.addToIndex(title: "Banana", content: "🍌")

Later:

spotlightSearch.search(title: "Banana")

It will find the title, but will not give me back the custom attribute value. If I put a breakpoint after "// Always nil" and use po attributeSet I will get

(lldb) po attributeSet
{
    "_kMDItemBundleID" = "de.axelspringer.SearchMac";
    "_kMDItemDomainIdentifier" = "com.company.some";
    "_kMDItemExpirationDate" = "2018-08-26 00:00:00 +0000";
    "_kMDItemExternalID" = MyUniqueIdBanana;
    "com_company_some_originalData" = "\Ud83c\Udf4c";
    kMDItemTitle = Banana;
}

So the value is there, but Spotlight will not return it to me. Already tried to use NSData instead of NSString for the custom attribute, but same result.

Also found this orphaned question in the Apple developer forums:

CSCustomAttributeKey valueForCustomKey not working


回答1:


I believe it's iOS issue. While it's not fixed, maybe Apple will allow you to use a private API to do your thing.

So, attributeSet has private Dictionaries attributes and customAttributes. You can try to get those values using Key Value Coding and ObjC:

NSDictionary *attributes = [attributeSet valueForKey:@"attributes"];
id customData = attributes[originalDataKeyName];

OR

NSDictionary *customAttributes = [attributeSet valueForKey:@"customAttributes"];
id customData = customAttributes[originalDataKeyName];

Key type in those dictionaries is either NSString* or CSCustomAttributeKey*, so you can try supplying both originalDataKeyName and originalDataKey.



来源:https://stackoverflow.com/questions/51542593/how-to-get-custom-value-back-from-spotlight-with-cscustomattributekey

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!