问题
I have implemented NSCoreDataCoreSpotlightDelegate, and I missed out the part where the default expirationDate is 1 month, now items that I have added 3 months ago are not showing up in the search index.
How do I get NSCoreDataCoreSpotlightDelegate to reindex all the items?
I used to be able to call this:
let container = NSPersistentContainer(name: "MyApp")
let psd = NSPersistentStoreDescription(url: FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "group.com.kiwlm.MyApp")!.appendingPathComponent("MyApp.sqlite"))
let mcdcsd = MyCoreDataCoreSpotlightDelegate(forStoreWith:psd, model: container.managedObjectModel)
container.persistentStoreDescriptions = [psd]
psd.setOption(mcdcsd, forKey:NSCoreDataCoreSpotlightExporter)
// uncomment the following to reindex all items
// mcdcsd.searchableIndex(CSSearchableIndex.default(), reindexAllSearchableItemsWithAcknowledgementHandler: {})
And the first time, it will reindex all the items, but if I re-run the app with the above line uncommented again, it will not reindex.
If I uninstall the app, install back, then uncomment the above line, then it will index all again for the first time.
How do I get it to reindex everything again?
回答1:
It happens because implementation of NSCoreDataCoreSpotlightDelegate use beginIndexBatch and endIndexBatchWithClientState to reindexAllSearchableItems. So it's saving index state. When you invoke reindexAllSearchableItems Spotlight will check the state and reindex only new items. When you delete the app you also delete index state. At first launch state is empty and NSCoreDataCoreSpotlightDelegate index all items.
I think for your purpose much better to set expirationDate instead of reindex all items. You can do it at MyCoreDataCoreSpotlightDelegate by override attributeSet:
override func attributeSet(for object: NSManagedObject) -> CSSearchableItemAttributeSet? {
guard let attributeSet = super.attributeSet(for: object) else { return nil }
if object.entity.name == "YourEntityName" {
// Setup necessary attributes
attributeSet.setValue(Date.distantFuture, forKey: "expirationDate")
}
return attributeSet
}
To check expirationDate of searchable items you can use CSSearchQuery:
class QueryExample {
var query : CSSearchQuery? = nil
func startQuery(withTitle title : String) {
var allItems = [CSSearchableItem]()
// All the items that start with the specified title property using case insensitive comparison
let queryString = "title == \"*\(title)*\"c"
let attributes = ["title", "displayName", "keywords",
"contentType"]
self.query = CSSearchQuery(queryString : queryString,
attributes : attributes)
self.query?.foundItemsHandler = { (items : [CSSearchableItem])
-> Void in
allItems.append(contentsOf: items)
}
self.query?.completionHandler = { (error ) -> Void in
for item in allItems {
print("expirationDate:\(item.expirationDate)")
}
}
self.query?.start()
}
}
Invoke query like this:
override func viewDidLoad() {
let query = QueryExample()
query.startQuery(withTitle: "S")
}
And you should see expirationDate at console:
expirationDate:4001-01-01 00:00:00 +0000
来源:https://stackoverflow.com/questions/55794439/ios-nscoredatacorespotlightdelegate-how-to-reindex-all-items