2

私は定期的にプラグイン (NSBundles をロード) を使用して、いくつかの機能をカプセル化しています。プラグインの 1 つで 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 のみが受信され、それ以外は何も受信されません。

同じ問題に取り組んでいる人々の投稿を 1 つまたは 2 つ見つけました。そのうちの 1 つ ( James Bucanek in Oh notifications, where are you? ) は、CFRunLoopRun(); を呼び出して彼の問題を解決しました。startQuery および CFRunLoopStop(CFRunLoopGetCurrent ()); の直後。クエリが実行されたとき。1 つの問題は、このように開始された実行ループが同期的であるのに対し、NSMetadataQuery は明らかに非同期であることです。もう 1 つの問題は、プラグインで 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 に答える