在我的應用程序中,我從Web服務中獲取JSON。這個JSON包含我想下載的幾個文件的URL。使用NSURLSessionDownloadTask一個接一個下載文件
我想用NSURLSessionDownloadTask
一個一個下載每個文件(等待第一個下載完成,直到第二個下載完成,等等等等)。我還想跟蹤寫入的總字節數,以便我可以更新UI。
非常感謝!
在我的應用程序中,我從Web服務中獲取JSON。這個JSON包含我想下載的幾個文件的URL。使用NSURLSessionDownloadTask一個接一個下載文件
我想用NSURLSessionDownloadTask
一個一個下載每個文件(等待第一個下載完成,直到第二個下載完成,等等等等)。我還想跟蹤寫入的總字節數,以便我可以更新UI。
非常感謝!
NSURLSessionDownloadTask就像你知道NSOperationQueues不像NSURLConnection(它可以封裝在一個NSOperation裏面)一樣不會很好地播放。
一個選擇是將所有的url添加到一個數組,然後在任務的completionHandler中,簡單地排隊下一個項目。
所以,你可能在一個循環中創建任務,調用每個任務完成處理內部progressBlock,存儲任務的數組,隊列中的每個任務的完成處理程序中的下一個任務:
- (void)addRequestsWithURLs:(NSArray *)urls
progressBlock:(void (^)(NSUInteger numberOfFinishedOperations, NSUInteger totalNumberOfOperations, NSURLSessionDownloadTask *task,NSURL *location, NSURLResponse *response, NSError *error))progressBlock {
__block NSUInteger numberOfFinishedOperations = 0;
NSUInteger totalNumberOfOperations = [urls count];
for (NSString *url in urls) {
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:url]];
__block NSURLSessionDownloadTask *task = [self.session downloadTaskWithRequest:request
completionHandler:^(NSURL *location, NSURLResponse *response, NSError *error) {
//downloadFileSomewhere
++numberOfFinishedOperations;
if (progressBlock) {
progressBlock(numberOfFinishedOperations, totalNumberOfOperations,task,destination != nil ? [NSURL fileURLWithPath:destination] : nil,response,error);
}
//queueNext
[self processCompletedTask:task];
}];
//stores an array of NSURLSessionTasks
[self.tasksWaitingToBeQueued addObject:task];
}
}
- (void)processCompletedTask:(NSURLSessionTask *)completedTask {
//clean up and queue next one
[self.tasksWaitingToBeQueued removeObject:completedTask];
nextTask = [self.tasksWaitingToBeQueued firstObject];
if (nextTask) {
[nextTask resume];
}
}
注意
在這個例子中,我將進度表示爲完成的任務數,而不是字節數,這是推薦的方法(它也更簡單)。要使用字節指示進度,您需要事先知道要下載的總字節數(因爲您想顯示進度條),並且還要實現NSURLSession委託並監視每個任務的進度,捕獲下載的字節並更新您的塊。如果你的服務器沒有告訴你總的字節數,那麼你可能需要爲每個資源做一個HEAD請求並聚合這些大小。就個人而言,這種解決方案是複雜的,可以簡單地通過將進度指示爲下載的文件數來解決。
要做到這一點可能是這個樣子:
- (void)URLSession:(NSURLSession *)session
downloadTask:(NSURLSessionDownloadTask *)downloadTask
didWriteData:(int64_t)bytesWritten
totalBytesWritten:(int64_t)totalBytesWritten
totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite {
self.totalBytesWritten += totalBytesWritten;
NSUInteger totalProgressSoFar = self.totalBytesWritten;
NSUInteger totalExpectedBytes = self.totalExpectedBytes;
//you would need to capture some progress block locally - beware of retain cycles
self.progressBlock(totalProgressSoFar/totalExpectedBytes)
}
當你完成你應該progressBlock爲零設置爲prevent any retain cycles。
非常感謝您的回答。我用你提出的建議,它似乎工作。再次感謝 ! – Vinestro 2014-10-13 11:57:43
@Vinestro真棒!聽到那個消息很開心 :) – 2014-10-14 12:47:55
我認爲我的解決方案不是你要找的?請評論和說明它是不正確的? – 2014-10-12 06:57:04