有人可以为我指出正确的方向,以了解如何正确监控应用程序 iCloud 容器中的文件何时更改?我的代码基于我查看过的 Apple 和其他 iCloud 教程,但它们都没有处理 iCloud 容器的更新,只是使用初始查询。我已经为此工作了三个星期,但没有成功。我在应用程序中使用 UIDocument 保存到应用程序 iCloud 容器。由于 UIDocument 在添加文档时不会发送通知,因此当应用程序在多个设备上运行时,我无法在另一台 iOS 设备上更新该应用程序。通过监视 UIDocument UIDocumentStateChangedNotification,更改和删除文档可以正常工作。
当应用程序启动或从后台恢复时,我使用查询来初步检查 iCloud 容器,这可以很好地获取设备上 iCloud 容器中的所有文件,包括在应用程序未处于活动状态时添加的任何文档。当发布 NSMetadataQueryDidFinishGatheringNotification 时,我禁用更新以处理查询结果,然后启用查询更新。有时我在启用来自 NSMetadataQueryDidUpdateNotification 的更新后不久会收到一两个更新通知,但仅此而已。永远不会有任何进一步的更新通知,也永远不会来自被添加到 iCloud 容器的文档。
我知道 iCloud 使用的代码有些复杂,我不希望任何人检查我的代码(我提供了一个摘录供参考)来纠正它。如果有人可以向我指出有关在应用程序执行期间跟踪 iCloud 容器更改的细节的更多信息,我将不胜感激。
谢谢,
弗雷德
开始查询的代码摘录:
-(void)loadDocument {
// set iCloud URL to nil for local storage to start
NSURL *ubiq = nil;
// if iCloud is selected get the iCloud container URL
if ([_useiCloud isEqualToString:@"YES"]) {
// get the app iCloud container URL
ubiq = DefaultMemoDataController.iCloudContainerURL;
}
// if iCloud URL is available and user chooses to use iCloud, set the query for app memo file names
if (ubiq) {
// adding to see if not creating another query prevents crash resuming from background
if (!self.query) {
self.query = [[NSMetadataQuery alloc] init];
}
// set the scope of the query to look in iCloud documents
[self.query setSearchScopes:[NSArray arrayWithObject:NSMetadataQueryUbiquitousDocumentsScope]];
// set search to look for a group of file names by setting up a predicate
// use the note file name format for the app
NSPredicate *pred = [NSPredicate predicateWithFormat:@"%K like 'FOLMemo_*'", NSMetadataItemFSNameKey];
// set the query to search with the predicate.
[self.query setPredicate:pred];
// set up a notification when the query is complete because the query is an asynchronous call (off the main queue)
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(queryDidFinishGathering:)
name:NSMetadataQueryDidFinishGatheringNotification
object:self.query];
// start the query.
[self.query startQuery];
// not sure this is needed, but want to make sure same query is started again for updates.
DefaultMemoDataController.query = self.query;
}
}
查询完成时的代码
-(void)queryDidFinishGathering:(NSNotification *)notification {
// stop the query while processing the query results to prevent changes while processing
NSMetadataQuery *query = [notification object];
[query disableUpdates];
// not sure is needed but want to make sure resume updates on same query
DefaultMemoDataController.query = query;
// stop looking for query did finish notifications since the query was completed.
[[NSNotificationCenter defaultCenter] removeObserver:self
name:NSMetadataQueryDidFinishGatheringNotification
object:query];
// start looking for query updates
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(processQueryUpdate:)
name:NSMetadataQueryDidUpdateNotification
object:query];
// load the data from the query
[self loadData:query];
}
处理查询的代码:
-(void)loadData:(NSMetadataQuery *)query {
// add all the memos from the query results to the app memos dictionary
for (NSMetadataItem *item in [query results]) {
// get the URL for the memo
NSURL *url = [item valueForAttribute:NSMetadataItemURLKey];
// load the memo text from the url
FOLMemoDoc *doc = [[FOLMemoDoc alloc] initWithFileURL:url];
// open the note
[doc openWithCompletionHandler:^(BOOL success) {
if (success) {
// add the memo UIDocument object to the memo dictionary
// need temp dictionary since can't change a property dictionary for some reason
NSMutableDictionary * tempDict = [NSMutableDictionary dictionaryWithDictionary:DefaultMemoDataController.masterMemoDictionary];
[tempDict setObject:doc forKey:doc.memoDictionaryKey];
DefaultMemoDataController.masterMemoDictionary = [NSMutableDictionary dictionaryWithDictionary:tempDict];
NSNotification *notice = [NSNotification notificationWithName:kFlashofLightUpdateMemoNotice
object:doc];
[[NSNotificationCenter defaultCenter] postNotification:notice];
} else {
// failed to open document, should probably alert the user
}
}];
}
// enable query updates
[query enableUpdates];
}