これを解決しようとすると、すでに頭痛の種になっています。現在のアプリでは、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?
}
ここでのアドバイスは本当に大歓迎です。
それが実際に行うこと:
iCloud ドキュメント コンテナー内のファイルを (上書きによって) 直接変更しても、クエリは実行されません。
setUbiquitous:NO、ローカル ファイルへの書き込み、setUbiquitous:YES のシーケンスでファイルを変更すると、クエリが 1 回起動し、変更が検出され、同じファイルを再度変更すると、クエリ ハンドラが呼び出されません。
したがって、上記の 1. のような iCloud ファイルへの書き込み方法が NEW ファイルに適用されることを Apple ドキュメントで確認したにもかかわらず、既存のファイルを変更する必要があるようです。
しかし、とにかく、クエリ メカニズムを繰り返し実行するにはどうすればよいでしょうか。
乾杯...