2

これを解決しようとすると、すでに頭痛の種になっています。現在のアプリでは、iCloud を使用してドキュメントを保存していますが、データに UIDocument ベースのストレージを使用することはできません。そこで私のアプローチは、WWDC 2012 の第 237 条 (高度な iCloud ドキュメント ストレージ) に従い、ドキュメントを靴箱アプリのように扱うことでした。

実際の問題は、NSMetadataQuery を作成して iCloud ドキュメント フォルダの変更を監視し、ファイルの変更に注意するときに発生します。クエリをセットアップし、NSMetadataQueryDidFinishGatheringNotification のオブザーバーで開始します。起動したら、クエリの更新を有効にし、NSMetadataQueryDidUpdateNotification のオブザーバーをセットアップします。後者は 1 回のファイル変更に対して 1 回しか機能せず、同じファイルまたは他のファイルのその後の変更に対して繰り返し起動する方法がわかりませんでした。ここにいくつかのコード部分があります:

- (void)startMonitoringDocumentsFolder: (id)sender
{
    if (self.queryDocs != nil)
        return;

    NSLog(@"startMonitoringDocumentsFolder:");

    self.queryDocs = [[NSMetadataQuery alloc] init];
    [queryDocs setSearchScopes:[NSArray arrayWithObject:NSMetadataQueryUbiquitousDocumentsScope]];

    NSPredicate*    pred = [NSPredicate predicateWithFormat:@"%K like '*.nwa' or %K like '*.NWA'", NSMetadataItemFSNameKey, NSMetadataItemFSNameKey];

    [self.queryDocs setPredicate:pred];

    NSNotificationCenter*   center    = [NSNotificationCenter defaultCenter];
    NSOperationQueue*       mainQueue = [NSOperationQueue mainQueue];

    // I'm using the blocks version because I'm planning to setup observers for the same tracking name...
    self.observeGatherDocs = [center addObserverForName: NSMetadataQueryDidFinishGatheringNotification
                                                 object: self.queryDocs
                                                  queue: mainQueue
                                             usingBlock: ^(NSNotification* note)
    {
        [self queryDidFinishGathering:note];
    }];
    [self.queryDocs startQuery];
}

- (void)queryDidFinishGathering:(NSNotification *)notification
{
    NSLog(@"queryDidFinishGathering:");
    NSMetadataQuery*    query = [notification object];

    if (query == queryDocs)
    {
        NSLog(@"--> for queryDocs");
        NSNotificationCenter*   center    = [NSNotificationCenter defaultCenter];
        NSOperationQueue*       mainQueue = [NSOperationQueue mainQueue];

        [center removeObserver: observeGatherDocs];
        self.observeGatherDocs = nil;
        self.observeUpdateDocs = [center addObserverForName: NSMetadataQueryDidUpdateNotification
                                                     object: query
                                                      queue: mainQueue
                                                 usingBlock: ^(NSNotification* note)
        {
            [self queryDidUpdateDocumentsFolder:note];
        }];

        [query enableUpdates];
    }
}

- (void)queryDidUpdateDocumentsFolder:(NSNotification *)notification
{
    NSLog(@"queryDidUpdateDocumentsFolder:");
    NSMetadataQuery*    query = [notification object];

    [query disableUpdates];

    for (NSMetadataItem* item in [query results])
    {
        // find and handle file changes here w/out any command calls to the query itself
        ...
    }

    if (self.needDownload)
        [self triggerDownloadThread];

    // ---- BEGIN code part added to solve the problem ---- //
    // re-create the observer
    NSNotificationCenter*   center    = [NSNotificationCenter defaultCenter];
    NSOperationQueue*       mainQueue = [NSOperationQueue mainQueue];

    [center removeObserver: observeUpdateDocs];
    self.observeUpdateDocs = [center addObserverForName: NSMetadataQueryDidUpdateNotification
                                                 object: query
                                                  queue: mainQueue
                                             usingBlock: ^(NSNotification* note)
    {
        [self queryDidUpdateDocumentsFolder:note];
    }];
    // ---- END code part added to solve the problem ---- //

    [query enableUpdates];
    // that's all with the query, am I missing something?
}

ここでのアドバイスは本当に大歓迎です。

それが実際に行うこと:

  1. iCloud ドキュメント コンテナー内のファイルを (上書きによって) 直接変更しても、クエリは実行されません。

  2. setUbiquitous:NO、ローカル ファイルへの書き込み、setUbiquitous:YES のシーケンスでファイルを変更すると、クエリが 1 回起動し、変更が検出され、同じファイルを再度変更すると、クエリ ハンドラが呼び出されません。

したがって、上記の 1. のような iCloud ファイルへの書き込み方法が NEW ファイルに適用されることを Apple ドキュメントで確認したにもかかわらず、既存のファイルを変更する必要があるようです。

しかし、とにかく、クエリ メカニズムを繰り返し実行するにはどうすればよいでしょうか。

乾杯...

4

1 に答える 1

3

さらに努力して調査した後、私は驚くべき解決策を見つけました。したがって、他の誰かがつまずいた場合、私は自分の経験を共有しているだけです。

  1. オブザーバーインスタンス変数は、参照を保持するものとして保持する必要があります(または、ARCを使用する場合は強力です)。
  2. 更新を有効にする前に、オブザーバーを再作成する必要があります。

それがすべてのようです。今のところ、それは機能しているようです。

于 2012-12-29T17:51:50.277 に答える