NSMetadataQuery - The Rules For OperationQueue?

I typically avoid NSMetadataQuery because I always found the API to be a bit peculiar but for this feature I'm working on I'm not sure it is worth the effort to implement this functionality in my own way. Plus it seems pretty fast.

What I find strange is I set the operationQueue to get notifications off the main thread. But also when I set the queue the system yells at me anytime I make a change to NSMetadataQuery that alters the query. So I found this recommendation (requirement) in the documentation :

NSMetadataQuery *query = // Initialize and set up a query
[query.operationQueue addOperationWithBlock:^{
    [query startQuery];
}];

I find this API design to be odd, but maybe I'm just weird. So there are a bunch of properties that can be changed while the query is already running (predicate etc.) and they implicitly stop/start the query and it seems all these calls need to be routed through the query.operationQueue like above? For example if I change the predicate while the query is already started it seems I have to:

[query.operationQueue addOperationWithBlock:^{
        query.predicate = predicate;
}];

The query already knows its operationQueue. Why does the caller have to plumb these calls through the operation queue manually? -stopQuery does not result in an error/warning when called off the operationQueue but is doing so safe? Or do I have to do:

[query.operationQueue addOperationWithBlock:^{
        [query stopQuery];
}];

Really what I was expecting was to provide a queue for the notification callbacks. I wasn't expecting to manually have to confine the query to its own queue.

Answered by DTS Engineer in 889855022

Ah, cool, that’s exactly what I was looking for.

I had a look at the origin of that message and it’s interesting. Obviously NSMetadataQuery was designed for a run loop world, with the queue support added later on. So this check has to handle both cases. The logic looks something like this:

if not started then
  ok = true
else if we have a queue then
  ok = NSOperationQueue.currentQueue is equal to that queue
else
  … the run loop case …
end if

So, if you’ve assigned a queue then you get that message based on the result of the currentQueue class property. Which means that your overall conclusion is correct: If you want to change properties on the fly, bounce to the queue and do the work there.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Hmm, I'll just wrap NSMetadataQuery behind my own class I think. I am assuming all properties need to be set on the operation queue, and I call start/stop on the operation queue as well.

But also when I set the queue the system yells at me anytime I make a change to NSMetadataQuery that alters the query.

Can you be more specific about what “yells at me” means? What are the actual symptoms here?

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

If you change properties that implicitly cause the query to stop/restart on another queue (say from the main queue) the system logs out:

<NSMetadataQuery:> has been started, but a modification to it was made from a different run loop or queue. Here's the backtrace: (

... )

Accepted Answer

Ah, cool, that’s exactly what I was looking for.

I had a look at the origin of that message and it’s interesting. Obviously NSMetadataQuery was designed for a run loop world, with the queue support added later on. So this check has to handle both cases. The logic looks something like this:

if not started then
  ok = true
else if we have a queue then
  ok = NSOperationQueue.currentQueue is equal to that queue
else
  … the run loop case …
end if

So, if you’ve assigned a queue then you get that message based on the result of the currentQueue class property. Which means that your overall conclusion is correct: If you want to change properties on the fly, bounce to the queue and do the work there.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

NSMetadataQuery - The Rules For OperationQueue?
 
 
Q