Ios 使用NSURLSession下载多个文件,并将其进度保持在后台状态
我使用NSURLSession下载了一个文件,它工作正常,现在我必须在后台下载三个文件,还必须在UIProgress中管理它们的进度。我的单次下载代码如下Ios 使用NSURLSession下载多个文件,并将其进度保持在后台状态,ios,ios7,nsurlconnection,nsurlsession,Ios,Ios7,Nsurlconnection,Nsurlsession,我使用NSURLSession下载了一个文件,它工作正常,现在我必须在后台下载三个文件,还必须在UIProgress中管理它们的进度。我的单次下载代码如下 - (IBAction)startBackground:(id)sender { // Image CreativeCommons courtesy of flickr.com/charliematters NSString *url = @"http://farm3.staticflickr.com/2831/982389
- (IBAction)startBackground:(id)sender
{
// Image CreativeCommons courtesy of flickr.com/charliematters
NSString *url = @"http://farm3.staticflickr.com/2831/9823890176_82b4165653_b_d.jpg";
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:url]];
self.backgroundTask = [self.backgroundSession downloadTaskWithRequest:request];
[self setDownloadButtonsAsEnabled:NO];
self.imageView.hidden = YES;
// Start the download
[self.backgroundTask resume];
}
- (NSURLSession *)backgroundSession
{
static NSURLSession *backgroundSession = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
NSURLSessionConfiguration *config = [NSURLSessionConfiguration backgroundSessionConfiguration:@"com.shinobicontrols.BackgroundDownload.BackgroundSession"];
backgroundSession = [NSURLSession sessionWithConfiguration:config delegate:self delegateQueue:nil];
});
return backgroundSession;
}
#pragma mark - NSURLSessionDownloadDelegate methods
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite
{
double currentProgress = totalBytesWritten / (double)totalBytesExpectedToWrite;
dispatch_async(dispatch_get_main_queue(), ^{
self.progressIndicator.hidden = NO;
self.progressIndicator.progress = currentProgress;
});
}
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didResumeAtOffset:(int64_t)fileOffset expectedTotalBytes:(int64_t)expectedTotalBytes
{
// Leave this for now
}
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location
{
// We've successfully finished the download. Let's save the file
NSFileManager *fileManager = [NSFileManager defaultManager];
NSArray *URLs = [fileManager URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask];
NSURL *documentsDirectory = URLs[0];
NSURL *destinationPath = [documentsDirectory URLByAppendingPathComponent:[location lastPathComponent]];
NSError *error;
// Make sure we overwrite anything that's already there
[fileManager removeItemAtURL:destinationPath error:NULL];
BOOL success = [fileManager copyItemAtURL:location toURL:destinationPath error:&error];
if (success)
{
dispatch_async(dispatch_get_main_queue(), ^{
UIImage *image = [UIImage imageWithContentsOfFile:[destinationPath path]];
self.imageView.image = image;
self.imageView.contentMode = UIViewContentModeScaleAspectFill;
self.imageView.hidden = NO;
});
}
else
{
NSLog(@"Couldn't copy the downloaded file");
}
if(downloadTask == cancellableTask) {
cancellableTask = nil;
} else if (downloadTask == self.resumableTask) {
self.resumableTask = nil;
partialDownload = nil;
} else if (session == self.backgroundSession) {
self.backgroundTask = nil;
// Get hold of the app delegate
SCAppDelegate *appDelegate = (SCAppDelegate *)[[UIApplication sharedApplication] delegate];
if(appDelegate.backgroundURLSessionCompletionHandler) {
// Need to copy the completion handler
void (^handler)() = appDelegate.backgroundURLSessionCompletionHandler;
appDelegate.backgroundURLSessionCompletionHandler = nil;
handler();
}
}
}
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error
{
dispatch_async(dispatch_get_main_queue(), ^{
self.progressIndicator.hidden = YES;
[self setDownloadButtonsAsEnabled:YES];
});
}
您可以让多个NSURLSessionDownloadTask使用同一NSSession,并且每个NSURLSessionDownloadTask都在同一主队列上逐个执行 成功下载后,他们会调用:
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location
如果下载100MB的MP4和10KB的pic,它们将以不同的顺序返回到该方法中
因此,要跟踪此会话中返回的会话和下载任务
在调用web服务之前,需要设置字符串标识符
要区分/跟踪您设置的NSURLSessions
session.configuration.identifier
要区分NSURLSessionDownloadTask,请使用
downloadTask_.taskDescription
downloadTask_.taskDescription = [NSString stringWithFormat:@"%@",urlSessionConfigurationBACKGROUND_.identifier];
例如,在我的项目中,我下载了许多用户喜爱的视频和它们的缩略图
每个项目都有一个id,例如1234567
所以我需要为每个最喜欢的人打两个电话
所以我创建了两个标识符
"1234567_VIDEO"
"1234567_IMAGE"
然后调用了两个ws调用,并在session.configuration.identifier中传入标识符
http://my.site/getvideo/1234567
"1234567_VIDEO"
http://my.site1/getimage/1234567
"1234567_IMAGE"
iOS7将在后台下载项目,应用程序可以返回睡眠状态
完成后会调用
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location
然后我得到
session.configuration.identifier
"1234567_IMAGE"
将其拆分并检查值
1234567_IMAGE
"1234567"
"_IMAGE" > item at location is a MP4 so save as /Documents/1234567.mp4
"_VIDEO" > item at location is a jpg so save as /Documents/1234567.jpg
如果要调用3个URL,则每个NSSession可以有一个NSURLSessionDownloadTask
file 1 - NSSession1 > NSURLSessionDownloadTask1
file 2 - NSSession2 > NSURLSessionDownloadTask2
file 3 - NSSession3 > NSURLSessionDownloadTask3
当应用程序位于前台时,这似乎可以正常工作。
但是我在使用后台传输和后台提取时遇到了问题。
第一个NSSession>NSURLSessionDownloadTask1将返回,然后不会调用任何其他任务
因此,在一个NSSession1中有多个NSURLSessionDownloadTask更安全
file 1 - NSSession1 > NSURLSessionDownloadTask1
file 2 - > NSURLSessionDownloadTask2
file 3 - > NSURLSessionDownloadTask3
做这件事时要小心
调用NSSession FinishTasks和Invalidate not invalidateAndCancel
//[session invalidateAndCancel];
[session finishTasksAndInvalidate];
invalidateAndCancel将停止会话,而不会完成其他下载任务。。。你的问题是什么?如果我必须下载三个文件,这段代码只适用于一次下载。我将如何管理..我没有得到..请帮助获取多个文件。如果你可以为一个文件执行此操作,将其扩展到进一步下载有什么困难?就像在代码中一样,它正在创建后台会话NSURLSessionConfiguration*config=[NSURLSessionConfiguration backgroundSessionConfiguration:@“com.shinobicontrols.BackgroundDownload.BackgroundSession”];如何处理多个文件我每次都需要一个不同的包标识符,而且进度条也有问题它总是在更新进度条..看到很多无用的评论,比如“What is your question”(你的问题是什么)真让人难过。。。问题是非常清楚的,“如果你可以为一个文件做这件事,那么扩展到进一步下载有什么困难?”。如果你知道如何解决这个问题,为什么不写下一个答案呢?NSURLSession如何让你知道当所有的文件都下载完毕,而应用程序不需要背景?当所有下载任务完成时,委托方法确实会被调用,但只有在我将我的应用程序设置为后台时才会被调用。当应用程序仍在运行时,我需要它。@NYCTechEngineer将所有任务添加到数组中,然后使用let downloadsCompleted=(downloadstasks.indexOf({$0.state==NSURLSessionTaskState.running})=nil)?真:假,表示他们已经完成。