Question

By default NSMetaDataQuery results notifications are received on the main thread. It seems you have to call query.startQuery on the main thread, but you can use [query.setOperationQueue:] to set the queue to which results notifications will be sent.

Ideally I want a background thread to be receiving these results and processing them and depending on what files are found, I will set variables or post notifications to the main thread.

What I don't understand is how I create the operational queue and how I process the notification on this queue. Sample code for whatever classes are required and details of where and how they should be created would be great. I have read the Apple docs but can't get my head around how you create a queue that can process notifications.

Thanks

Was it helpful?

Solution

You can try to use this code to process notifications in background thread:

   NSMetadataQuery *query = [NSMetadataQuery new];
   [query enableUpdates];
   // Subscribe to query updates and process then in background thread
   [[NSNotificationCenter defaultCenter] addObserverForName:
    NSMetadataQueryDidUpdateNotification
   object:nil queue:[NSOperationQueue new]
   usingBlock:^(NSNotification __strong *notification)
   {
      // disable the query while iterating
    [query disableUpdates];
     for (NSMetadataItem *item in query.results)
     {
         //do here everything you want with the results 
        //e.g. get values with [item valueForAttribute:NSMetadataItemFSNameKey];
         }          
       [query enableUpdates];
        }];
    [query startQuery];

Just for the tip:

 [NSOperationQueue mainQueue] // added operations execute on the main thread
 [NSOperationQueue new] // iOS 4 and higher - guaranteed to be on the background thread

P.S to process first results you should subscribe to NSMetadataQueryDidFinishGatheringNotification - it will be posted when the receiver has finished with the initial result-gathering phase of the query and for all subsequent updates you should subscribe to NSMetadataQueryDidUpdateNotification as in my example because as you know queries have two phases: the initial gathering phase that collects all currently matching results and a second live-update phase.

OTHER TIPS

This was very helpful. This is the code I used to implement this in Swift if anyone is looking for this:

let nf = NotificationCenter.default

    //add background queue observer for updates during live phase
    nf.addObserver(forName: NSNotification.Name.NSMetadataQueryDidUpdate, object: nil, queue: self.backGroundQueue, using:{_ in 
        self.query.disableUpdates()
        self.resultsArray = self.query.results as! [ResultItem]
        self.query.enableUpdates()
    })

    //add background queue observer for updates during gathering
    nf.addObserver(forName: NSNotification.Name.NSMetadataQueryGatheringProgress, object: nil, queue: self.backGroundQueue, using:{_ in
        self.query.disableUpdates()
        self.resultsArray = self.query.results as! [ResultItem]
        print("progressing... ")
        print("number of results: \(self.query.results.count)")
        self.query.enableUpdates()
    })

    //add background queue observer for finishing gathering phase
    nf.addObserver(forName: NSNotification.Name.NSMetadataQueryDidFinishGathering, object: nil, queue: self.backGroundQueue, using:{_ in
        self.query.disableUpdates()
        self.resultsArray = self.query.results as! [ResultItem]
        self.query.enableUpdates()
    })


    self.query.searchScopes = [self.thePath]
    self.query.predicate = self.getPredicateToRun()

    self.query.start()
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top