如何告诉iOS从iCloud Drive下载文件并获得进度反馈

时间:2014-10-29 02:58:33

标签: objective-c cocoa ios8 icloud

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

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

有人可以向我解释一下吗?

P.S。有没有比我更高代表的人用UIDocumentPicker和iCloudDrive标记这篇文章?

2 个答案:

答案 0 :(得分:7)

据我所知,您只能使用以下方式检索进度反馈 Ubiquitous Item Downloading Status Constants仅提供3种状态:

  • NSURLUbiquitousItemDownloadingStatusCurrent
  • NSURLUbiquitousItemDownloadingStatusDownloaded
  • NSURLUbiquitousItemDownloadingStatusNotDownloaded

因此,您无法获得量化的进度反馈,只有部分也可以下载。

为此,您需要准备并启动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];
}

答案 1 :(得分:2)

来自NSMetadataQuery的进度反馈通过通知发生。更新频率默认为每秒一次(可以通过设置notificationBatchingInterval来更改)。更新的对象封装在通知的userInfo dict中,作为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];
}