3

監視しているドキュメントの削除を検出する明確な方法が見つかりません(アプリが気にするドキュメントのリストをキャッシュします)。

デバイス1の場合:ドキュメントを削除すると、

        [fileCoordinator coordinateWritingItemAtURL:fileURL options:NSFileCoordinatorWritingForDeleting
          error:&err byAccessor:^(NSURL* writingURL) {
             [fileManager removeItemAtURL:writingURL error:nil];

これはDevice1で正常に機能し、すべてが同期されたままになります。NSMetadataQueryデバイス2の場合:通知に依存しようとしていました:

最初のファイルリストは、NSMetadataQueryDidFinishGatheringNotification ドキュメントの追加/変更で問題なく機能します。NSMetadataQueryDidUpdateNotification

Device1でファイルを削除すると、奇妙な結果が得られます。NSMetadataQueryDidUpdateNotificationすべてのドキュメント(削除されたものを除く)がリストされた状態で更新が行われます。不足しているファイルが削除されたこと、または更新が削除されたことをどのように検出するのかわかりません。通知はその目的のためでした

質問1:何をチェックする必要がありますか?

NSFilePresenter私はiCloudURLのとして登録するという別のルートを試しました:

- (NSURL *)iCloudDocumentsURL
{
    return [[NSFileManager defaultManager] URLForUbiquityContainerIdentifier:nil] URLByAppendingPathComponent:@"Documents"];
}

そのURLのファイルが変更されると、プロトコルを介して呼び出されるようになりNSFilePresenterましたが、コールバックがあいまいなため、ロジックを実行して欠落しているドキュメントを特定するのは非常に遅くなります。私が返す唯一の呼び出しは- (void)presentedItemDidChange; 、を介してコールバックを取得することを期待していたことですが、- (void)accommodatePresentedSubitemDeletionAtURL:(NSURL *)url completionHandler:(void (^)(NSError *errorOrNil))completionHandler このメソッドは呼び出されません。

質問2:それを機能させる方法はありますか?

4

3 に答える 3

3

以前にiCloudから報告されたファイルを追跡しているため、削除されたファイルは現在のiCloudリストに含まれていません。したがって、2つのリストを比較して、どちらが削除されたかを確認します。

これは、「ファイルマネージャー」ビューコントローラーで行っていることです。これは、マスタービューでのファイル「アイコン」の位置のキーを含むファイルエントリのNSMutableDictionaryを保持しているためです。更新の通知を受け取り、その更新によってファイルが増減した場合、それらのファイルの変更に基づいてアイコンの変更をアニメーション化します。

于 2012-06-15T15:33:20.170 に答える
2

tobinjimは、NSMetadataQueryが毎回結果セット全体を返すという点で正しいです。帯域幅を節約するために変更のみが送信されることを期待していましたが、RTFMを正しく実行しませんでした。

それを理解すると、iOSライブラリのバグに遭遇しました。これは、あるデバイスでドキュメントを削除し、iCloudクエリの更新が他のデバイスで発生したときに発生したクラッシュでした。

    2012-06-25 13:15:12.343 app[19779:707] *** -[NSMutableIndexSet indexGreaterThanOrEqualToIndex:]: message sent to deallocated instance 0xdaae2c0
    (gdb) bt
    #0  0x31937870 in ___forwarding___ ()
    #1  0x31892650 in __forwarding_prep_0___ ()
    #2  0x373cc676 in __NSIndexSetEnumerate ()
    #3  0x373a1ee8 in -[NSIndexSet enumerateIndexesWithOptions:usingBlock:] ()
    #4  0x371c1f08 in -[LBQuery _processUpdates] ()
    #5  0x373571a6 in -[NSObject(NSThreadPerformAdditions) performSelector:onThread:withObject:waitUntilDone:modes:] ()
    #6  0x3737ffa4 in -[NSObject(NSThreadPerformAdditions) performSelector:onThread:withObject:waitUntilDone:] ()
    #7  0x371c2274 in -[LBQuery processUpdates] ()
    #8  0x373a88d6 in -[NSMetadataQuery _update] ()

私はこの問題の原因を見つけたと思います。LuketheHiestermanによるプレゼンテーションの新しいIOS6サンプルコードを確認していました。以前のiCloudサンプルアプリのようにNSMetadataQueryのdisable/enableUpdatesが呼び出されていないことに気づきました。これらへのすべての呼び出しを削除しました。また、NSMetadataQueryDidUpdateNotification呼び出しを処理するメソッドを変更して、非同期でキューに入れて実行するようにしました。

NSMetadataQueryのスレッド間で競合状態が発生しているようです。一部の呼び出しではクエリの結果は問題ありませんが、他の場合はリリースされ、結果はNSZombieのものとして表示されます(現在のlldbよりもはるかに優れたgdbのおかげです)。したがって、スレッド間でクエリを有効または無効にすると、解放されたオブジェクトを呼び出すことによってLBQueryがクラッシュします。

NSMetadataQueryの有効化と無効化をすべて削除したことで、私のアプリも高速化されたようで、iCloudの方がはるかに安定しているようです。

于 2012-06-25T20:58:09.430 に答える