I am at my wits end after trying to add a routine to my controller to search the user's computer for user files with specified user (Mavericks+) tags. I am running into a block where the search will start, but no results are returned and the operation queue is nil.
Here is the code:
class myController: NSWindowController {
//define metadataQuery
var metadataQuery: NSMetadataQuery!
var metadataQueryDidUpdateObserver: AnyObject?
var metadataQueryDidFinishGatheringObserver: AnyObject?
//initialize notificationsCenter
let notificationsCenter = NotificationCenter.default
func doSpotlightSearch(){
//add observers
notificationsCenter.addObserver(self, selector: "initalGatherComplete:", name: NSNotification.Name.NSMetadataQueryDidFinishGathering, object: nil)
notificationsCenter.addObserver(self, selector: "batchReturned:", name: NSNotification.Name.NSMetadataQueryDidUpdate, object: nil)
metadataQuery = NSMetadataQuery()
metadataQuery.searchScopes = [NSMetadataQueryIndexedLocalComputerScope]
metadataQuery.predicate = NSPredicate(format: "kMDItemUserTags == 'myTags.testTag'")
//start search
metadataQuery.start()
//test to see if query is up and running
while metadataQuery.isGathering{
print(metadataQuery.operationQueue?.operationCount)
print ("result count: \(metadataQuery.resultCount)")
sleep(1)
}
func batchReturned(_ sender: NSNotification) {
print("Running batchReturned func")
let resultCounter = metadataQuery.resultCount
print("Number of results:\(resultCounter)")
let notificationsCenter = NotificationCenter.default
notificationsCenter.removeObserver(self, name: NSNotification.Name.NSMetadataQueryDidFinishGathering, object: nil)
}
func initalGatherComplete(_ sender: NSNotification) {
print("Running initialGatherComplete func")
metadataQuery.stop()
let resultCounter = metadataQuery.resultCount
print("Number of results:\(resultCounter)")
let notificationsCenter = NotificationCenter.default
notificationsCenter.removeObserver(self, name: NSNotification.Name.NSMetadataQueryDidFinishGathering, object: nil)
}
When I run the above code, it shows the results queue as being nil and the result count as zero. Even if I take out the isGathering loop, the batchReturned and initialGatherComplete functions never get called.
I suspect that there may be an issue with the predicate formatting, but this works fine when I put the query into the terminal with mdfind.
From documentation of NSMetadataQuery.start()
method: This method must be called from the receiver’s operationQueue or on the main thread.
If you are not calling start()
method from main thread you are responsible to create OperationQueue
yourself and start if from there, e.g:
// Declare on class-level
private lazy var queryOperationQueue: OperationQueue = {
let queue = OperationQueue()
queue.maxConcurrentOperationCount = 1 // restriction for NSMetadataQuery
return queue
}()
...
func doSpotlightSearch() {
metadataQuery = NSMetadataQuery()
metadataQuery.searchScopes = [NSMetadataQueryIndexedLocalComputerScope]
metadataQuery.predicate = NSPredicate(format: "kMDItemUserTags == 'myTags.testTag'")
// assign queue to NSMetadataQuery
metadataQuery.operationQueue = queryOperationQueue
// run query from its queue
metadataQuery.operationQueue?.addOperation {
metadataQuery.start()
}
}
Hope it's clear.