
Programming with Spotlight
Pages: 1, 2, 3, 4
Examine a Specific File's Metadata
Out next topic investigates Spotlight's ability to examine a specific file's metadata, and it's surprisingly easy. To illustrate, let's enhance our example project. For the sake of time, we'll stay focused and add a text view object that displays the metadata for a specific file. In your own applications, you'd probably be doing something more involved. You can find plenty of good Cocoa tutorials that illustrate broader topics involving user interaction, file browsers, etc. here on MacDevCenter if you need that additional context.
Modify your controller files (changes are in bold):
For "Controller.h":
// Controller.h
// SpotlightExamples
#import <Cocoa/Cocoa.h>
@interface Controller : NSObject {
IBOutlet NSButton* openSearchWindowButton;
IBOutlet NSTextView* metadataInfoView;
IBOutlet NSButton* displayMetadataButton;
}
- (IBAction)openSearchWindowAction:(id)sender;
- (IBAction)displayMetadataAction:(id)sender;
@end
For "Controller.m":
// Controller.m
// SpotlightExamples
#import "Controller.h"
@implementation Controller
- (IBAction)openSearchWindowAction:(id)sender
{
OSStatus resultCode=noErr;
//Replace "Search Text" with user input
resultCode=HISearchWindowShow((CFStringRef)@"Search Text", kNilOptions);
if (resultCode != noErr) {
NSLog(@"Failed to open search window");
//Could use NSAlert class to display interactive dialog
}
}
- (IBAction)displayMetadataAction:(id)sender
{
//create a CF-compliant object representing a file and its metadata using
//a Carbon level call
//add in a path to an existing file on your system
CFStringRef path = CFSTR("/Users/matthew/temp.txt");
MDItemRef item = MDItemCreate(kCFAllocatorDefault, path);
//pull out the metadata attribute names
CFArrayRef attributeNames = MDItemCopyAttributeNames(item);
//use toll-free bridging to load up an NSArray for convenience
NSArray* array = (NSArray*)attributeNames;
NSEnumerator *e = [array objectEnumerator];
id arrayObject;
//placeholders
NSMutableString *info = [NSMutableString stringWithCapacity:50];
CFTypeRef ref;
while ((arrayObject = [e nextObject]))
{
ref =
MDItemCopyAttribute(item, (CFStringRef)[arrayObject description]);
//cast to get an NSObject for convenience
NSObject* tempObject = (NSObject*)ref;
[info appendString:[arrayObject description]];
[info appendString:@" = "];
[info appendString:[tempObject description]];
[info appendString:@"\n"];
}
//set the info in the text view
[metadataInfoView insertText:info];
}
@end
You'll need to update your instantiated controller to reflect changes in your source code by dragging the "Controller.h" file onto the main Interface Builder palette and choose to "Replace" when prompted. Without this change, the controller won't recognize the new outlets and action you just added.
- Spruce up your application's main window in Interface Builder
- Add an NSButton and rename it "Display Metadata"
- Add an NSTextView (from the "Cocoa-Text" tab)
- Set the outlet and action for the new button
- Set the outlet for the text view the same as with the button (it doesn't have any actions)
With all that done, ensure that you've specified a file that exists on your system in method openSearchWindowAction:
. I just created a temporary text file for purposes of illustration. Again, your application would be doing all sorts of fancy user interaction here; we're being simple on purpose. "Build and Go" to see the action. If something's not working, double check your outlets and connections. You can always add NSLog
messages to help troubleshoot.
Your project is now capable of examining a file's metadata.
You can get the project file for this second portion here.
