Oscar Franco
Oscar Franco

Reputation: 6220

How to do a Spotlight search in Swift (NSMetadataQuery)?

I'm trying to do a Spotlight search inside a mac app. Here is the code I have so far:

import Foundation

let nf = NotificationCenter.default

class FileSearcher {

  public static let sharedInstance = FileSearcher()
  
  var query: NSMetadataQuery? {
    willSet {
      if let q = self.query {
        q.stop()
      }
    }
  }

  init() {
    print("Setting observer")
    nf.addObserver(forName: .NSMetadataQueryDidStartGathering, object: nil, queue: .main, using: {_ in

      print("Query did start gathering")
    })

    nf.addObserver(forName: .NSMetadataQueryDidUpdate, object: nil, queue: .main, using: {_ in

      print("QUery results updated \(self.query?.resultCount)")
    })
    nf.addObserver(forName: .NSMetadataQueryDidFinishGathering, object: nil, queue: .main, using: {_ in
      print("Got results \(self.query?.results)")
    })
  }


  func searchFile(_ oq: String) {
    print("Searching \(oq)")
    query = NSMetadataQuery()
    let predicate = NSPredicate(format: "%K ==[cd] %@", NSMetadataItemFSNameKey ,oq)
    query?.searchScopes = [NSMetadataQueryIndexedLocalComputerScope]
    query?.predicate = predicate
    query?.start()
  }
}


The problem is the query did update and query did finish gathering are never triggered. Maybe it has to do something with my predicate? I'm trying to do a fuzzy search.

Any help is much appreciated!

Upvotes: 0

Views: 214

Answers (2)

Gene De Lisa
Gene De Lisa

Reputation: 3838

The query takes an OperationQueue

theMetadataQuery.operationQueue?.addOperation {
    if self.theMetadataQuery.isStarted {
        self.theMetadataQuery.stop()
    }
    self.theMetadataQuery.start()
}

Upvotes: 0

Oscar Franco
Oscar Franco

Reputation: 6220

Found the problem, which was not mentioned in any of the Stack Overflow answers I saw and apparently it is documented somewhere. You need to call it from the main dispatch queue:

func searchFile(_ oq: String) {
    if(!oq.isEmpty) {
      query = NSMetadataQuery()
      let predicate = NSPredicate(format: "%K ==[cd] %@", NSMetadataItemFSNameKey, oq)
      query?.searchScopes = [NSMetadataQueryIndexedLocalComputerScope]
      query?.predicate = predicate
      DispatchQueue.main.async {
        self.query?.start()
      }
    }
  }

Upvotes: 0

Related Questions