Querying Metadata With Spotlight

With the introduction of Spotlight it has now become easier for applications to locate file system objects on disk. Leveraging the Spotlight APIs in your application you can query the meta-data store and content index to find files, plugins, and other data for processing. This article illustrates one example in how Cocoa developers can use some of these APIs to search for image files.





Setting Up Your Search

In order for a Cocoa application to search Spotlight metadata, you must create and setup a query or NSMetadataQuery. In doing so, you must determine how you want to be notified for key stages of the search process using NSNotificationCenter, and how you want the search results sorted using NSSortDescriptor. Listing 1 below shows an example controller class and it's init method you would use to do this. Notice that we will pass along our NSMetadataQuery object as part of the notification.

Listing 1: Setting Up Your Search - Initialization.

@interface MyController : NSObject
{
    NSMetadataQuery* query;
}
@end

- (id)init
{
    if (self = [super init])
    {
        query = [[NSMetadataQuery alloc] init];

        // setup our Spotlight notifications
        NSNotificationCenter *nf = [NSNotificationCenter defaultCenter];
        [nf addObserver:self selector:@selector(queryNotification:) name:nil object:query];

        // initialize our Spotlight query
        [query setSortDescriptors:
            [NSArray arrayWithObject:
                [[[NSSortDescriptor alloc] initWithKey:(id)kMDItemFSName ascending:YES] autorelease]]];

        [query setDelegate: self];
    }
    return self;
}

Next you want to define your notification method so you can be called when a search has started, is in progress, and has finished. With this notification you can even find out when a query result has changed, when new files have been added, modified, or removed. We use the object passed in as our NSMetadataQuery. We will use NSMetadataQueryDidFinishGatheringNotification to start processing our search results. You can use the other notifications to drive a progress indicator dialog for example.

Listing 2: Listening for Notifications


- (void)queryNotification:(NSNotification*)note
{
    // the NSMetadataQuery will send back a note when updates are happening.

    // by looking at the [note name], we can tell what is happening
    if ([[note name] isEqualToString:NSMetadataQueryDidStartGatheringNotification])
    {
        // the query has just started
        NSLog(@"search: started gathering");
    }
    else if ([[note name] isEqualToString:NSMetadataQueryDidFinishGatheringNotification])
    {
        // at this point, the query will be done. You may recieve an update later on.
        NSLog(@"search: finished gathering");

        [self loadSlidesFromQueryResult:note];
    }
    else if ([[note name] isEqualToString:NSMetadataQueryGatheringProgressNotification])
    {
        // the query is still gatherint results...
        NSLog(@"search: progressing...");
    }
    else if ([[note name] isEqualToString:NSMetadataQueryDidUpdateNotification])
    {
        // an update will happen when Spotlight notices that a file as added,
        // removed, or modified that affected the search results.
        NSLog(@"search: an update happened.");
    }
}

Now that we have our search query configured we must identify "what" we are searching for using an NSPredicate. In our case we setup a predicate for searching the content type of a file or kMDItemContentTypeTree attribute. We use the Uniform Type Identifier "public.image".

Back to Top 

Executing a Search

Listing 3: Start searching for image files.

- (void)startSlideQuery:(NSString*)fromPath
{
    // setup Spotlight query to look for image files and start it up
    [query setPredicate: [NSPredicate predicateWithFormat: @"(kMDItemContentTypeTree == 'public.image')"]];
    [query setSearchScopes: [NSArray arrayWithObjects: fromPath, nil]];
    [query startQuery];
}

Back to Top 

Processing Search Results

As you may have noticed earlier when we receive the NSMetadataQueryDidFinishGatheringNotification to start processing our search results, the following method loadSlidesFromQueryResult will be called. The NSNotification contains the information about our search results described as the NSMetadataQuery. We iterate through each result as a NSMetadataItem and obtain its store path described in the query attribute kMDItemPath.

Listing 4: Parsing the meta data results.

- (void)loadSlidesFromQueryResult:(NSNotification*)notif
{
    NSArray* results = [(NSMetadataQuery*)[notif object] results];

    // iterate through the array of results, and match to the existing stores
    int count = [results count];
    if (count == 0)
    {
        // no image files were found
    }
    else
    {
        // use Spotlight's search query results and load the images

        int i;
        for (i = 0; i < count;  i++)
        {
            // get the result item
            NSMetadataItem* item = [results objectAtIndex: i];

            NSString* storePath = [[item valueForAttribute:
                    (NSString *)kMDItemPath] stringByResolvingSymlinksInPath];

            if ((storePath != nil) && ([storePath length] > 0))
            {
                // create a URL for the represented path and look for an existing store
                NSURL* storeURL = [NSURL fileURLWithPath: storePath];

                NSImage* image = [[[NSImage alloc] initWithContentsOfURL: storeURL] autorelease];
                if (image != nil)
                {
                    // add the image to a table or an array...
                }
            }
        }
    }
}

Back to Top 

Cleaning Up

As always, we want to clean up after ourselves by removing us from the notification center and releasing our query.

Listing 5: Example dealloc method.

- (void)dealloc
{
    [[NSNotificationCenter defaultCenter] removeObserver:self];
    [query release];

    [super dealloc];
}

Back to Top 

Related Documentation

Back to Top 

Document Revision History

DateNotes
2007-06-04Describes how a Cocoa application can search Spotlight metadata.

Posted: 2007-06-04


Did this document help you?
Yes: Tell us what works for you.
It’s good, but: Report typos, inaccuracies, and so forth.
It wasn’t helpful: Tell us what would have helped.