2

我经常使用插件(加载的 NSBundles)来封装一些功能。我现在想在我的一个插件中使用 NSMetadataQuery,但遇到了我无法解决的线程问题。

在插件的主类中,我这样设置查询:

NSMetadataQuery *mdQuery = [[NSMetadataQuery alloc] init];
    [mdQuery setPredicate:[NSPredicate predicateWithFormat:@"(kMDItemFSName LIKE 'Project *')"]];
    [[NSNotificationCenter defaultCenter] addObserver:self 
                                             selector:@selector(processQuery:) 
                                                 name:nil 
                                               object:mdQuery];

    [mdQuery startQuery];

通知被以下人员捕获:

- (void)processQuery:(NSNotification *)notification
{
    NSMetadataQuery *mdQuery = [notification object];

    if ([[notification name] isEqualToString:NSMetadataQueryDidStartGatheringNotification]) {
        NSLog(@"%@ %@ Query started", [self class], NSStringFromSelector(_cmd));

    } else if ([[notification name] isEqualToString:NSMetadataQueryGatheringProgressNotification]) {

        NSLog(@"%@ %@ %ld", [self class], NSStringFromSelector(_cmd), (long)[mdQuery resultCount]);

    } else if ([[notification name] isEqualToString: NSMetadataQueryDidFinishGatheringNotification]) {
        NSUInteger theResultCount = [mdQuery resultCount];
        theResultCount = 10; //for now
        for (NSUInteger i; i < theResultCount; i++) {
            NSLog(@"%@ %@ %ld %@", [self class], NSStringFromSelector(_cmd), (long)i, [mdQuery resultAtIndex:i]);
        }

    } else {
        NSLog(@"%@ %@ NSMetadataQueryDidUpdateNotification: %@", [self class], NSStringFromSelector(_cmd), notification);
    }
}

此代码在应用程序中运行良好,但使用插件运行时,只收到 NSMetadataQueryDidStartGatheringNotification ,没有别的。

我发现一两个帖子里有同样问题的人,其中一个(哦通知中的 James Bucanek,你在哪里?)通过调用 CFRunLoopRun(); 解决了他的问题。在 startQuery 和 CFRunLoopStop(CFRunLoopGetCurrent ()) 之后;当查询完成时。一个问题是这样启动的运行循环是同步的,而 NSMetadataQuery 显然是异步的,另一个是在插件中它从未通过 NSMetadataQueryGatheringProgressNotification。然后我尝试给 NSMetadataQuery 自己的线程,但同样,只收到了 NSMetadataQueryDidStartGatheringNotification。我不知道问题是否可以解决,但我真的很想提供一些意见。

4

2 回答 2

1

代替:

NSMetadataQuery *mdQuery = [[NSMetadataQuery alloc] init];
// ...
[mdQuery startQuery];

和:

dispatch_async(dispatch_get_main_queue(), ^{
    NSMetadataQuery *mdQuery = [[NSMetadataQuery alloc] init];
    // ...
    [mdQuery startQuery];
});

(如果您需要以 Leopard 或更早版本为目标,请-performSelectorOnMainThread:withObject:waitUntilDone:改用。)

于 2011-07-19T22:10:08.310 回答
0

如果代码是通过捆绑加载而不是编译到应用程序中,那么应该不会发生任何不同的情况。

当您加载一个 Cocoa 包时,包中的类被加载到应用程序的地址空间中,并基本上成为应用程序的一部分。除非您特别指定,否则捆绑代码不会在单独的线程或运行循环中运行。

我不相信这是一个运行循环或线程问题。是什么让你认为它是?

你确定你的包中开始查询的对象在结果返回时还没有被释放吗?是什么在坚持它?

于 2011-06-07T02:25:36.403 回答