Cocoa: Using NSPredicate and NSMetadataQuery

Apple, Cocoa, General

Hi Apple Cocoa developers. Here are some more tips and tricks for Cocoa development.

On Tiger, there is a new class called NSMetadataQuery that allows you to do some cool Spotlight searches. See the “Spotlighter” demo application included in /Developer/Examples/AppKit/Spotlighter.

Creating a predicate to get the search results that you want can be tricky, but alas, there is an easy way!

First, do a search inside of Finder that has the criteria you want. For example, below is a search for all images recently created:

Spotlightsearchexampleinfinder

Hit the save button and save it to your desktop. You can then show the info that Saved Search Query inside of Finder and see the Query it is using:

Searchqueryexample

You can also drag and drop it onto TextEdit to open up the file (it is just a simple XML plist). You can then extract the query via copy and paste:

(kMDItemContentTypeTree = ‘public.image’) && (kMDItemFSCreationDate >= $time.today(-7)) && (kMDItemContentType != com.apple.mail.emlx) && (kMDItemContentType != public.vcard)

So, you want to test this query be executing it from the command line. You should be able to do an “mdfind” and paste it after it, however, that won’t work! You must escape the $ with a slash since the shell interprets the slash as a file input.

You also have to quote the entire thing, as follows:

mdfind “(kMDItemContentTypeTree = 'public.image') &&
    (kMDItemFSCreationDate >= \$time.today(-7)) &&
    (kMDItemContentType != com.apple.mail.emlx) &&
    (kMDItemContentType != public.vcard)”

And, thus you can use it from a command prompt:

Commandpromptquerymdfind
(sorry for the ugly wrapping).

Okay — so, one would think they can paste this into a predicate and just use it as-is, right?

Well, no! The following would normally work:

[NSPredicate predicateWithFormat:@“kMDItemContentTypeTree = ‘public.image’ && (kMDItemFSCreationDate >= $time.today(-7)) && kMDItemContentType != ‘com.apple.mail.emlx’”] ;

But a small bug prevents it from actually parsing the text due to the $time reference (it might even crash!). You must single quote the $time part to get it to work:

[NSPredicate predicateWithFormat:@“kMDItemContentTypeTree = ‘public.image’ && (kMDItemFSCreationDate >= ‘$time.today(-7)’) && kMDItemContentType != ‘com.apple.mail.emlx’”] ;

Then, it should all be okay!

Have fun. Happy programming. Long live MacOS.



Subscribe
Notify of
guest

3 Comments
Inline Feedbacks
View all comments
Matt Brook

Thanks for the tip regarding single quoting the time portion of NSPredicates, saved me a lot of headaches.
Cheers
Matt

Jofell Gallardo

A really great article! I’ve been struggling for the date bit in MDQueryRef, and now I’m using your tips. Thanks a lot!

Subscribe to new posts:

You'll get an email whenever a I publish a new post to my blog and nothing more. -- Corbin

As an Amazon Associate I earn from qualifying purchases.

(c) 2008-2024 Corbin Dunn

Privacy Policy

Subscribe to RSS feeds for entries.

70 queries. 0.154 seconds.

Log in