【问题标题】:How do I tell iOS to download a file from iCloud Drive and get progress feedback如何告诉 iOS 从 iCloud Drive 下载文件并获得进度反馈
【发布时间】:2014-12-24 16:02:04
【问题描述】:

我正在使用 UIDocumentPicker 选择文件,但如果文件很大,打开可能需要一段时间,这对用户来说不是特别好的体验。

我查看了 Apple 的 iCloud 编程指南,但我似乎无法弄清楚如何实际下载文件并获得一些进度反馈,文档太模糊了。我知道我应该对 NSMetadataItems 做一些事情,但实际上并没有太多解释如何获得和使用它。

谁能给我解释一下?

附:有比我更高代表的人可以用 UIDocumentPicker 和 iCloudDrive 标记这篇文章吗?

【问题讨论】:

标签: objective-c cocoa ios8 icloud


【解决方案1】:

据我所知,您只能使用 Ubiquitous Item Downloading Status Constants 仅提供 3 种状态:

  • NSURLUbiquitousItemDownloadingStatusCurrent
  • NSURLUbiquitousItemDownloadingStatusDownloaded
  • NSURLUbiquitousItemDownloadingStatusNotDownloaded

因此您无法获得量化的进度反馈,只有部分 aka 是否已下载。

为此,您需要准备并启动您的NSMetadataQuery,添加一些观察者并使用NSURLUbiquitousItemDownloadingStatusKey 键检查您的NSMetadataItem 的下载状态。

self.query = [NSMetadataQuery new];
self.query.searchScopes = @[ NSMetadataQueryUbiquitousDocumentsScope ];
self.query.predicate = [NSPredicate predicateWithFormat:@"%K like '*.yourextension'", NSMetadataItemFSNameKey];

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(queryDidUpdate:) name:NSMetadataQueryDidUpdateNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(queryDidFinishGathering:) name:NSMetadataQueryDidFinishGatheringNotification object:nil];

[self.query startQuery];

那么,

- (void)queryDidUpdate:(NSNotification *)notification
{
    [self.query disableUpdates];

    for (NSMetadataItem *item in [self.query results]) {
        NSURL *url = [item valueForAttribute:NSMetadataItemURLKey];
        NSError *error = nil;
        NSString *downloadingStatus = nil;

        if ([url getResourceValue:&downloadingStatus forKey:NSURLUbiquitousItemDownloadingStatusKey error:&error] == YES) {
            if ([downloadingStatus isEqualToString:NSURLUbiquitousItemDownloadingStatusNotDownloaded] == YES) {
                // Download
            }
            // etc.
        }
    }

    [self.query enableUpdates];
}

【讨论】:

  • 那么,如果我想找到一个特定的文件,我只是在谓词中使用它吗?
  • 是的,您可以从 NSMetadataItem 中查找特定名称、带有您的扩展名、路径、大小、创建日期或在 attribute keys 中定义的任何文件的所有文件。我编辑了答案以添加示例。
  • 还有一个问题,为什么要关闭更新,然后再打开?
  • 我们需要在迭代查询结果之前禁用/启用更新,因为它们可能会因实时更新而改变。从文档中:“除非您使用 enumerateResultsUsingBlock:或 enumerateResultsWithOptions:usingBlock:,否则您应该调用此方法”
【解决方案2】:

来自NSMetadataQuery 的进度反馈通过通知进行。更新频率默认为每秒一次(可通过设置notificationBatchingInterval 更改)。更新的对象被封装在通知的userInfo 字典中,作为NSMetadataItem 的数组。下载反馈包含在每个项目的密钥NSMetadataUbiquitousItemPercentDownloadedKey 中。由于数组在内部是可变的,我们需要在枚举结果时告诉NSMetadataQuery 禁用更新。这很重要,否则会发生奇怪的崩溃。

典型的实现可能如下所示:

- (void) queryDidUpdate:(NSNotification *)notification {

[self.mdQuery disableUpdates];// we don't want to receive a new update while we still process the old one

NSArray *addedItems     = notification.userInfo[NSMetadataQueryUpdateAddedItemsKey];
NSArray *remItems       = notification.userInfo[NSMetadataQueryUpdateRemovedItemsKey];
NSArray *changedItems   = notification.userInfo[NSMetadataQueryUpdateChangedItemsKey];

// add
for (NSMetadataItem *mdItem in addedItems) {
    NSURL *url          = [mdItem valueForKey:NSMetadataUbiquitousItemURLInLocalContainerKey];
    // do something...
}
// remove
for (NSMetadataItem *mdItem in remItems) {
    NSURL *url          = [mdItem valueForKey:NSMetadataUbiquitousItemURLInLocalContainerKey];
    // do something...
}
// change
for (NSMetadataItem *mdItem in changedItems) {
    NSURL *url          = [mdItem valueForKey:NSMetadataUbiquitousItemURLInLocalContainerKey];
        // uploading
        BOOL uploading  = [(NSNumber *)[mdItem valueForKey:NSMetadataUbiquitousItemIsUploadingKey] boolValue];
        if (uploading) {
            NSNumber *percent   = [mdItem valueForKey:NSMetadataUbiquitousItemPercentUploadedKey];
            cell.progressView.progress = percent.floatValue;
            // do something...
        }
        // downloading
        BOOL downloading    = [(NSNumber *)[mdItem valueForKey:NSMetadataUbiquitousItemIsDownloadingKey] boolValue];
        if (downloading) {
            NSNumber *percent   = [mdItem valueForKey:NSMetadataUbiquitousItemPercentDownloadedKey];
            cell.progressView.progress = percent.floatValue;
            // do something...
        }
    }
[self.mdQuery enableUpdates];
}

【讨论】:

    猜你喜欢
    • 2015-08-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-02-06
    • 1970-01-01
    • 2014-04-25
    • 2012-01-29
    • 2020-07-21
    相关资源
    最近更新 更多