Setting Up Your SearchIn 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 SearchListing 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 ResultsAs 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 UpAs 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 DocumentationBack to Top Document Revision HistoryDate | Notes |
---|
2007-06-04 | Describes how a Cocoa application can search Spotlight metadata. |
Posted: 2007-06-04
|