【发布时间】:2017-11-27 16:44:18
【问题描述】:
-
此方法设置背景对象。
- (void) downloadWithURL: (NSMutableArray *)urlArray pathArr: (NSMutableArray *)pathArr mediaInfo: (MediaInfo *)mInfo { bgDownloadMediaInfo = mInfo; reqUrlCount = urlArray.count; dict = [NSDictionary dictionaryWithObjects:pathArr forKeys:urlArray]; mutableDictionary = [dict mutableCopy]; backgroundConfigurationObject = [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:@"XXXXX"]; backgroundConfigurationObject.sessionSendsLaunchEvents = YES; backgroundConfigurationObject.discretionary = YES; backgroundSession = [NSURLSession sessionWithConfiguration: backgroundConfigurationObject delegate: self delegateQueue: [NSOperationQueue currentQueue]]; self.requestUrl = [urlArray objectAtIndex:0]; download = [backgroundSession downloadTaskWithURL:self.requestUrl]; [download resume]; } -
这些是完成处理程序。
#pragma Mark - NSURLSessionDownloadDelegate - (void)URLSession: (NSURLSession *)session downloadTask: (NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL: (NSURL *)location { LogDebug(@"Download complete for request url (%@)", downloadTask.currentRequest.URL); NSString *temp = [mutableDictionary objectForKey:downloadTask.currentRequest.URL]; NSString *localPath = [NSString stringWithFormat: @"%@",temp]; NSFileManager *fileManager = [NSFileManager defaultManager]; NSURL *destinationURL = [NSURL fileURLWithPath: localPath]; NSError *error = nil; [fileManager moveItemAtURL:location toURL:destinationURL error:&error]; LogDebug(@"Moving download file at url : (%@) to : (%@)", downloadTask.currentRequest.URL, destinationURL); reqUrlCount --; downloadSegment ++; // Handover remaining download requests to the OS if ([finalUrlArr count] != 0) { // remove the request from the array that got downloaded. [finalUrlArr removeObjectAtIndex:0]; [finalPathArr removeObjectAtIndex:0]; if ([finalUrlArr count] > 0) { // proceed with the next request on top. self.requestUrl = [finalUrlArr objectAtIndex:0]; download = [backgroundSession downloadTaskWithURL:self.requestUrl]; [download resume]; } } if ([adsArray count] > 0) { adsArrayCount --; // delegate back once all the ADs segments have been downloaded. if (adsArrayCount == 0) { for (int i = 0; i < [adsArray count]; i++) { NSArray *ads = [adsArray objectAtIndex: i]; for (int j = 0; j < [ads count]; j++) { MediaInfo *ad = [ads objectAtIndex: j]; [self setDownloadComplete: ad]; // skip sending downloadFinish delegate if the media is marked as downloadDone if (!ad.downloadDone) { [delegate MediaDownloadDidFinish: ad.mediaId error: NO]; } ad.downloadDone = YES; } } downloadSegment = 0; } } // delegate back once all the main media segments have been downloaded. if (reqUrlCount == 0) { [self setDownloadComplete: mediaInfo]; state = DownloadState_Done; // skip sending downloadFinish delegate if the media is marked as downloadDone if (!bgDownloadMediaInfo.downloadDone) { [delegate MediaDownloadDidFinish: bgDownloadMediaInfo.mediaId error: NO]; } bgDownloadMediaInfo.downloadDone = YES; [urlArr release]; [pathArr release]; [finalUrlArr release]; [finalPathArr release]; // invalidate the NSURL session once complete [backgroundSession invalidateAndCancel]; } } - (void)URLSession: (NSURLSession *)session task: (NSURLSessionTask *)task didCompleteWithError: (NSError *)error { if (error) { NSLog(@"Failure to download request url (%@) with error (%@)", task.originalRequest.URL, error); } } - (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite { // save the total downloaded size [self downloaderDidReceiveData:bytesWritten]; // enable the log only for debugging purpose. // LogDebug(@"totalBytesExpectedToWrite %llu, totalBytesWritten %llu, %@", totalBytesExpectedToWrite, totalBytesWritten, downloadTask.currentRequest.URL); } -
如果没有此代码(beginBackgroundTaskWithExpirationHandler),下载会在应用程序被推入后台时停止。
// AppDelegate_Phone.m - (void)applicationDidEnterBackground: (UIApplication *)application { NSLog(@"applicationDidEnterBackground"); UIApplication *app = [UIApplication sharedApplication]; UIBackgroundTaskIdentifier bgTask; bgTask = [app beginBackgroundTaskWithExpirationHandler:^{ [app endBackgroundTask:bgTask]; }]; }
【问题讨论】:
-
你的问题是......?
-
顺便说一句,后台会话的实例化并不真正属于
downloadWithURL:pathArr:mediaInfo:。如果您尝试下载两个文件怎么办?您不希望实例化两个后台会话。此外,完全不相关,将[NSOperationQueue currentQueue]用于委托队列似乎是不谨慎的(因为您不知道您是从哪个队列调用它的)。如果您碰巧从某个并发队列中调用它怎么办?离开这个nil并让它使用自己的串行队列进行后台会话的委托调用可能更安全。 -
didFinishDownloadingToURL引用finalUrlArr有点担心。您是否将这个finalUrlArr存储在持久存储中,然后在每次应用程序重新启动时重新加载它?请记住,在调用委托方法时,应用程序可能已经终止并重新启动。此外,您似乎一次下载一个文件,但您通常只是继续并开始后台会话的所有下载,而不是在每次下载结束时重新唤醒您的应用程序以开始下一次下载。这样更高效(电池电量和速度)。 -
@prokhorov - 预期行为:当应用程序被推到后台时下载应该继续(按主页按钮)实际:下载工作正常,只要应用程序在前台但下载停止按下主页按钮后。我可以通过使用 beginBackgroundTaskWithExpirationHandler 来解决问题,但根据苹果指南,我们不需要它来支持下载。
-
@Rob - 正如你所建议的,我尝试将 NSOperationQueue 设置为 nil。但这也无济于事。
标签: objective-c nsurlsessiondownloadtask