首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何确定iCloud文件夹中是否存在文件?

如何确定iCloud文件夹中是否存在文件?
EN

Stack Overflow用户
提问于 2013-07-06 03:14:53
回答 1查看 3.8K关注 0票数 6

我有一个iOS应用程序,可以在iCloud中存储文件。当我启动应用程序时,我想确定以前的设备是否已经上传了任何文件。我启动了第一个设备,它将文件添加到iCloud (我可以在Mac上的文件夹中看到它们)。然后,我在第二个设备上启动应用程序,并尝试使用下面的NSMetadataQuery来查看是否有任何文件被上传,但它返回0的结果。如果我继续运行这个查询,大约8-10秒后,它就会返回结果。

代码语言:javascript
复制
iCloudQuery = [[NSMetadataQuery alloc] init];

iCloudQuery.searchScopes = @[NSMetadataQueryUbiquitousDataScope];

NSString *filePattern = [NSString stringWithFormat:@"*.%@", @"txt"];

iCloudQuery.predicate = [NSPredicate predicateWithFormat:@"%K LIKE %@", NSMetadataItemFSNameKey, filePattern];

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(iCloudQueryDidFinishGathering:) name:NSMetadataQueryDidFinishGatheringNotification object:iCloudQuery];

[iCloudQuery startQuery];

当我收到通知时,查询的resultCount是0

代码语言:javascript
复制
- (void)iCloudQueryDidFinishGathering:(NSNotification *)notification
{    
    NSMetadataQuery *query = [notification object];
    [query disableUpdates];
    [query stopQuery];

    NSLog(@"Found %d results from metadata query", query.resultCount);
}

如果文件存在于NSMetadataQuery中,即使文件还没有下载,那么iCloud不应该返回一个resultCount吗?是否有任何方法来测试文件是否存在,除了在15-30秒之后尝试一个over和timing之外?

EN

回答 1

Stack Overflow用户

发布于 2013-07-06 08:32:59

查询可能需要一些时间才能从iCloud检索元数据。didFinishGathering最初可能只保存已经知道的结果,而不是它没有机会从iCloud那里听到的更改。

与其停止和启动NSMetadataQuery,不如设置一个并继续收听它,同时注册:

代码语言:javascript
复制
[[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(iCloudQueryDidUpdate:)
                                             name:NSMetadataQueryDidUpdateNotification
                                           object:iCloudQuery];

..。当他们进来的时候检索更新。因此,您还需要更改您的finishGathering方法,而不是停止查询,并在最后更改为enableUpdates。

您将不得不重新考虑您的方法,以便考虑到第一组结果还不一定知道所有的事情。更常见的是,NSMetadataQuery被用来监视iCloud,期望其他设备产生的变化可以随时出现--而不仅仅是在应用程序发布时。

如果您需要确保您拥有iCloud最最新的元数据,我发现唯一可靠的方法(在iOS 5和iOS 6上)是将一个小文件注入iCloud (通常以不同的名称命名,并使用UUID命名,以保证它是唯一的),然后在iCloudQueryDidUpdate:方法中,在查询返回该文件之前不考虑查询结果的完成,并且它的元数据报告说它也被上传到iCloud。一旦您拿回了它,您就可以相当肯定地从iCloud收到了最新的元数据。

在iCloudQueryDidUpdate中检查上传:使用:

代码语言:javascript
复制
int resultCount = [iCloudQuery resultCount];

for (int i = 0; i < resultCount; i++) {
  NSMetadataItem *item = [iCloudQuery resultAtIndex:i];

  BOOL isUploaded = [[item valueForAttribute:NSMetadataUbiquitousItemIsUploadedKey] boolValue];
  BOOL isDownloaded = [[item valueForAttribute:NSMetadataUbiquitousItemIsDownloadedKey] boolValue];
  NSURL *url = [item valueForAttribute:NSMetadataItemURLKey];
  BOOL documentExists = [[NSFileManager defaultManager] fileExistsAtPath:[url path]];

  // You'll need to check isUploaded against the URL of the file you injected, rather than against any other files your query returns
}

当你完成注入的文件时,别忘了删除它--否则每次你的应用程序启动时这些文件都会挂载起来。

编辑:

我实现这些检查的方式有一个内置的延迟,一旦我取出它,我就发现上面的情况并不完全可靠。

我已经删除了元数据项(使用Settings/iCloud/Storage & Backup/Manage在当前运行之前删除),在完整的元数据返回到注入的文件之前,我已经将其报告为上载和下载,并已存在于磁盘上。但是,一旦注入的文件被报告为上载、下载和本地存在于磁盘上,其中一个已删除的文件仍然在上载和下载的元数据中列出,但在磁盘上不存在。

因此,看起来正在发生的是,iCloud守护进程听说了对旧数据的挂起的删除,并在应用程序看到的元数据更新以反映这一点之前实际执行了删除操作。疯了,嗯?因此,我必须更新上面的建议,只有当项目被报告为下载、上传并使用[NSFileManager fileExistsAtPath:]方法存在于本地文件夹时,才能考虑查询结果是否完成。上面编辑的代码反映了这一点。

在此之后,您所能做的就是在执行查询结果之前插入1秒的延迟,以确保所有元数据都有时间被接收--尽管这是我讨厌做的事情。在代码中加入虚假的时间延迟,使其工作起来,我觉得有点接近黑魔法。这表明您并不真正理解正在发生的事情--尽管没有更多的钩子进入iCloud后面的处理,我们还能做什么呢?

票数 7
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/17499331

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档