Friday, April 22, 2011

Spotlighter and NSMetadataQuery

Apple's Spotlighter example tries to help us to become more familiar with NSMetadataQuery.
But it also contains a nasty bug, that let your derived code crash or let it become slower and slower.
The Spotlighter example does not crash, of course...

In -createSearchPredicate the example's author proposes to simply call
-setPredicate: followed by -startQuery.

Doing it this way produces multiple MDQuery instances under the hood.
All the created MDQuery objects do weakly reference your (single) NSMetadataQuery instance.
But your NSMetadataQuery instance only references one of them.
This does not pop up as long as you do not release the NSMetadataQuery instance in your code.

But if the instance of NSMetadataQuery gets freed, all the obsolete MDQuery objects continue to listen to changes (live update). On changes they try to invoke the freed NSMetadataQuery instance, which lets your app crash. NSMetadataQuery's -stopQuery method just frees the one and only MDQuery it references internally.

Solution:

// stop query if it already has been started
if ([myQuery isStarted] == YES)
[myQuery stopQuery];

// setting the predicate
[myQuery setPredicate:myPredicate];

// start or restart the query
if ([myQuery isStarted] == NO || [myQuery isStopped] == YES)
[myQuery startQuery];

No comments: