如何在iOS中下载多个mp4文件?

我在这个问题上坚持了最近2天。 请帮帮我。

我的要求是,如果我在第二视图控制器中在后台下载文件并且在下载开始后我弹出到第一视图控制器并且如果我再次推送到第二视图控制器那么应该继续该进度。

发生了什么:

  1. 我推到第二视图控制器。
  2. 我使用NSMutableURLRequestNSURLConnection开始下载。
  3. 如果我弹出到第一视图控制器并再次转到第二视图控制器,则所有显示为0.意味着如果在弹出期间进度为34%并再次按下时间,则在我的UI中显示0%,但下载继续照常进行。

我的日志也显示完美但UI没有显示。 我尝试了所有的答案。 一切都是同样的问题。

这是我的整个代码:

在App Delegate方法中:

CTAppDelegate.h

 @property (copy) void (^backgroundSessionCompletionHandler)(); 

CTAppDelegate.m

 - (void)application:(UIApplication *)application handleEventsForBackgroundURLSession:(NSString *)identifier completionHandler:(void (^)())completionHandler { self.backgroundSessionCompletionHandler = completionHandler; } 

2ndViewController.h

 - (IBAction)downloadBackground:(id)sender; - (IBAction)downloadImage:(id)sender; @property (strong, nonatomic) IBOutlet UIImageView *downloadedImage; @property (strong, nonatomic) IBOutlet UIProgressView *progressView; @end 

2ndViewController.m

 #import "CTViewController.h" #import "CTSessionOperation.h" #import "CTAppDelegate.h" static NSString *downloadUrl = @"http://sofzh.miximages.com/ios/ladee_9.4.13_nasa_edge_0.jpg"; @interface CTViewController () @property (nonatomic, strong) NSOperation *downloadOperation; @end @implementation CTViewController - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. self.progressView.progress = 0; self.downloadedImage.hidden = NO; self.progressView.hidden = YES; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } - (IBAction)downloadBackground:(id)sender { // [self downloadImageInBackground:YES]; [self.navigationController popViewControllerAnimated:YES]; } - (IBAction)downloadImage:(id)sender { [self downloadImageInBackground:NO]; } - (void)downloadImageInBackground:(BOOL)background{ if (self.downloadOperation){ return; } CTSessionOperation *operation = [CTSessionOperation new]; operation.downloadUrl = downloadUrl; operation.progressAction = ^(double bytesWritten, double bytesExpected){ double progress = bytesWritten / bytesExpected; dispatch_async(dispatch_get_main_queue(), ^{ self.progressView.progress = (float) progress; }); }; operation.completionAction = ^(NSURL *imageUrl, BOOL success){ dispatch_async(dispatch_get_main_queue(), ^{ if (success){ UIImage *image = [UIImage imageWithContentsOfFile:[imageUrl path]]; self.downloadedImage.image = image; NSLog(@"Done......."); } self.downloadedImage.hidden = NO; self.progressView.progress = 0; self.progressView.hidden = YES; self.downloadOperation = nil; }); }; operation.isBackground = background; [operation enqueueOperation]; self.downloadedImage.hidden = YES; self.progressView.hidden = NO; self.downloadOperation = operation; } @end 

Operation.h

  #import  typedef void (^CTProgressBlock)(double totalBytesWritten, double bytesExpected); typedef void (^CTCompletionBlock)(NSURL *imageUrl, BOOL success); @interface CTSessionOperation : NSOperation @property (nonatomic) NSURLSessionDownloadTask *downloadTask; @property (nonatomic) NSURLSession *session; @property (nonatomic, strong) NSString *downloadUrl; @property (strong) CTProgressBlock progressAction; @property (strong) CTCompletionBlock completionAction; @property (nonatomic, assign) BOOL isBackground; - (void)enqueueOperation; @end 

Operation.m

  #import "CTSessionOperation.h" #import "CTAppDelegate.h" @implementation CTSessionOperation - (NSOperationQueue *)operationQueue{ static NSOperationQueue *operationQueue = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ operationQueue = [NSOperationQueue new]; [operationQueue setMaxConcurrentOperationCount:NSOperationQueueDefaultMaxConcurrentOperationCount]; }); return operationQueue; } - (NSURLSession *)session { static NSURLSession *session = nil; static NSURLSession *backgroundSession = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration]; session = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:nil]; NSURLSessionConfiguration *backgroundConfiguration = [NSURLSessionConfiguration backgroundSessionConfiguration:@"com.captech.NSURLSample.BackgroundSession"]; backgroundSession = [NSURLSession sessionWithConfiguration:backgroundConfiguration delegate:self delegateQueue:nil]; }); return self.isBackground ? backgroundSession : session; } - (void)enqueueOperation{ [[self operationQueue] addOperation:self]; } #pragma mark - NSOperation - (void)start { if (!self.isCancelled){ NSURL *downloadURL = [NSURL URLWithString:self.downloadUrl]; NSURLRequest *request = [NSURLRequest requestWithURL:downloadURL]; self.downloadTask = [self.session downloadTaskWithRequest:request]; [self.downloadTask resume]; } } #pragma mark - NSURLSessionDownloadDelegate - (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location { NSFileManager *fileManager = [NSFileManager defaultManager]; NSArray *urls = [fileManager URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask]; NSURL *documentsDirectory = [urls objectAtIndex:0]; NSURL *originalUrl = [[downloadTask originalRequest] URL]; NSURL *destinationUrl = [documentsDirectory URLByAppendingPathComponent:[originalUrl lastPathComponent]]; NSError *error; [fileManager removeItemAtURL:destinationUrl error:NULL]; BOOL success = [fileManager copyItemAtURL:location toURL:destinationUrl error:&error]; if (self.completionAction){ self.completionAction(destinationUrl, success); } } - (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite { if (downloadTask == self.downloadTask && self.progressAction){ self.progressAction((double)totalBytesWritten, (double)totalBytesExpectedToWrite); } } - (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didResumeAtOffset:(int64_t)fileOffset expectedTotalBytes:(int64_t)expectedTotalBytes { } #pragma mark - NSURLSessionTaskDelegate - (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error { if (self.progressAction){ self.progressAction((double)task.countOfBytesReceived, (double)task.countOfBytesExpectedToReceive); } self.downloadTask = nil; } #pragma mark - NSURLSessionDelegate - (void)URLSessionDidFinishEventsForBackgroundURLSession:(NSURLSession *)session { CTAppDelegate *appDelegate = (CTAppDelegate *)[[UIApplication sharedApplication] delegate]; if (appDelegate.backgroundSessionCompletionHandler) { void (^completionHandler)() = appDelegate.backgroundSessionCompletionHandler; appDelegate.backgroundSessionCompletionHandler = nil; completionHandler(); } } @end 

这是我的完整代码。 请检查一下…… 🙂

我会处理下载与你如何做的有点不同:)

这是我将如何处理它:)

1.Declare一个NSOperation类并移动代码将文件下载到这个类

2.在您的NSOpertaion类中声明一个协议,该协议将向当前下载状态通知确认此协议的任何人

3.在你的第二个VC启动NSOpertaion并选择代表:)并相应地更新你的进度

  1. 在您的secondVC的viewWillDisappear中将其删除为委托,并将其作为委托添加回第二个VV的ViewWillAppear中的NSOperation

这里有一些相同的代码:)

downloadAssets.h

 #import  @protocol AssetDownloadStatusProtocol  -(void)updateStatusWithValue:(float) progress; @end @interface downloadAssets : NSOperation @property (nonatomic,weak) id delegate; @property (nonatomic,strong) NSString *urlToDownload; -(id)initWithURL:(NSString *)url; @end 

downloadAssets.m

  @implementation downloadChatAssets -(id)initWithURL:(NSString *)url{ self=[super init]; self.urlToDownload = url; appdelegate=(AppDelegate *)[[UIApplication sharedApplication] delegate]; return self; } - (void)main { // a lengthy operation @autoreleasepool { dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ if (self.isCancelled) { appdelegate.downloadingOperation = nil; return; } else{ NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration]; AFURLSessionManager *manager = ... //start downloading NSURLSessionDataTask *dataTask = [manager dataTaskWithRequest:URLRequest uploadProgress:nil downloadProgress:^(NSProgress * _Nonnull downloadProgress) { if (self.isCancelled) { appdelegate.downloadingOperation = nil; return; } self.progressAmount = downloadProgress.fractionCompleted; dispatch_async(dispatch_get_main_queue(), ^{ [self.delegate updateStatusWithValue:self.progressAmount]; }); } completionHandler:^(NSURLResponse * _Nonnull response, id _Nullable responseObject, NSError * _Nullable error) { //handle completion here }]; [dataTask resume]; } }); } } @end 

AppDelegate.h

 @property (nonatomic, Strong) NSOperation *downloadingOperation; 

SecondVC.h

 @interface SecondVC : UIViewController  

SecondVC.m

 -(void)viewWillAppear:(BOOL)animated{ [super viewWillAppear:YES]; if(appdelegate.downloadingOperation) { appdelegate.downloadingOperation.delegate = self; } } -(void)viewWillDisappear:(BOOL)animated{ [super viewWillDisappear:YES]; if(appdelegate.downloadingOperation) { appdelegate.downloadingOperation.delegate = nil; } } -(void)updateStatusWithValue:(float)progress{ dispatch_async(dispatch_get_main_queue(), ^{ //update your progress here [self.progressView updateProgressBarWithProgressValue:progress]; }); } 

而已 :)

随时开始下载操作:)

 appdelegate.downloadingOperation = yourDownloaderOperation; [yourDownloaderOperation start]; 

你想阻止它说

 [yourDownloaderOperation stop]; 

有更多的下载操作? 考虑使用NSOperationQueue或Array在appdelegate中保存NSOperations 🙂

编辑

根据您的评论请求,您可以在appDelegate中保留对CTOperation的引用。

 @property (nonatomic, Strong) CTOperation *downloadingOperation; 

您不需要声明协议,因为您已经声明了完成块和progressActionBlock 🙂

您所要做的就是,检查您的SecondVC viewWillAppear。

 -(void)viewWillAppear:(BOOL)animated{ [super viewWillAppear:YES]; if(appdelegate.downloadingOperation) { appdelegate.downloadingOperation.progressAction = ^(double bytesWritten, double bytesExpected){ double progress = bytesWritten / bytesExpected; dispatch_async(dispatch_get_main_queue(), ^{ self.progressView.progress = (float) progress; }); }; appdelegate.downloadingOperation.completionAction = ^(NSURL *imageUrl, BOOL success){ dispatch_async(dispatch_get_main_queue(), ^{ if (success){ UIImage *image = [UIImage imageWithContentsOfFile:[imageUrl path]]; self.downloadedImage.image = image; NSLog(@"Done......."); } self.downloadedImage.hidden = NO; self.progressView.progress = 0; self.progressView.hidden = YES; self.downloadOperation = nil; }); }; } } -(void)viewWillDisappear:(BOOL)animated{ [super viewWillDisappear:YES]; if(appdelegate.downloadingOperation) { appdelegate.downloadingOperation.progressAction = nil; appdelegate.downloadingOperation.completionAction = nil; } } 

并在你的downloadImageInBackground方法而不是self.downloadOperation = operation; 说’appdelegate.downloadingOperation = operation;

放弃

请注意,本答案中提供的代码仅用于解释概念。 我可能有语法或符号错误。 请不要盲目复制粘贴。

简单吧??? 有疑惑,ping我:)快乐编码:)