Uniquing NSMetadataItem's
Uniquing NSMetadataItem's
- Subject: Uniquing NSMetadataItem's
- From: Derrek Leute <email@hidden>
- Date: Tue, 12 Jul 2005 22:46:02 -0400
Warning: Complicated incoherent e-mail with frightening code....
My basic problem is that I need to combine query results from
multiple NSMetadataQuery searches so that there is only one of a
particular result in an NSMutable set object. The following relevant
code works (sorta):
[_groupQuery addObserver:self forKeyPath:@"results"
options:NSKeyValueObservingOptionNew context:nil];
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)
object change:(NSDictionary *)change context:(NSString *)context {
if ([keyPath isEqualToString:@"results"]) {
[NSThread detachNewThreadSelector:@selector
(searchResultsThread:) toTarget:self withObject:change];
}
}
- (void) searchResultsThread:(id)change {
NSAutoreleasePool *pool;
pool = [[NSAutoreleasePool alloc] init];
NSEnumerator *keyEnum=[[change objectForKey:@"new"]
objectEnumerator];
id item;
while (item = [keyEnum nextObject]) {
NSString *dictKey = [item valueForKeyPath:@"kMDItemPath"];
NSLog(@"%@",dictKey);
[itemDictLock lock];
id dictItem = [itemDict valueForKey:dictKey];
if (dictItem == nil) {
NSMutableDictionary *tempDict = [[NSMutableDictionary
alloc] init];
[tempDict setValue:dictKey forKey:@"itemPath"];
[tempDict setValue:[item
valueForKeyPath:@"kMDItemFSName"] forKey:@"name"];
[itemDict setValue:tempDict forKey:dictKey];
[tempItemsLock lock];
[tempItems addObject:tempDict];
[tempItemsLock unlock];
[self addLocalItemsObject:tempDict];
[tempDict release];
} else {
[tempItemsLock lock];
[tempItems addObject:dictItem];
[tempItemsLock unlock];
[self addLocalItemsObject:dictItem];
}
[itemDictLock unlock];
}
[tempItemsLock lock];
[self intersectLocalItems:tempItems];
[tempItemsLock unlock];
[pool release];
return;
}
When I ran this on a search that returns lots of results it starts
dozens of threads and brings my computer to a stand still. I added
the threading so that large searches would work in the background and
wouldn't block the interface. What I didn't realize is that
observeValueForKeyPath is called many times during long searches and
returns *the entire change dictionary* each time (it seems to include
all the items for the search each time it posts a dictionary).
On to the questions:
1. Is there a better way to combine results from multiple (concurrent
or consecutive) NSMetadataQuery's? The above code using the file path
as a unique key to an NSMutableDictionary whose objects are
NSDictionaries that I create if there isn't already a key that
matches. This is time consuming and must be threaded to not block the
interface. Could it be more effiicient? (ignore all the locking, even
the non-threaded version blocks for minutes or more)
2. The following link says I can distribute notifications to the
appropriate thread:
http://developer.apple.com/documentation/Cocoa/Conceptual/
Notifications/Tasks/Threading.html
This works fine for NSNotificationCenter messages, but I'm using
addObserver:forKeyPath:options:context to monitor changes to the
results array of an NSMetadataQuery. I do not believe this can
redirect that kind of notification. lacking that, is there a way to
receive notifications from that kind of observation inside a
particular thread?
3. Am I missing something entirely? I could move the NSMetadataQuery
inside the secondary thread so that it's notifications post to the
secondary thread (and only one worker thread started from init), but
then I need some way for the thread to know that the searchKey
(linked with bindings to an interface object) changed. And that still
doesn't solve the fact that uniquing the NSMetadataItem's using this
method is horribly slow.
I may have come up with a solution that writing this e-mail helped me
think of. Since I wrote it, I'm going to send it anyway and see what
all of you think.
Thanks
--Derrek
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Cocoa-dev mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden