Not able to get results for spotlight search for user tags with NSMetadataquery and kMDItemUserTags

248 views Asked by At

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.

1

There are 1 answers

0
Palli On BEST ANSWER

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.