ios - json如何在后台下载多个mp4文件以及iOS的进展?

  显示原文与译文双语对照的内容
110 4

我在这个问题上坚持了 2天。请你 帮帮 我 的 忙 。

如果在第二视图控制器中下载文件,并且下载后启动,我将弹出到 1st 视图控制器,如果我再次推到 2nd 视图控制器,那么应该继续进行。

这里发生了什么:

  • 我推送到第二个视图控制器。
  • 我开始使用 NSMutableURLRequestNSURLConnection 下载。
  • 如果我弹出 1st 位视图控制器,再转到 2nd 视图控制器,那么所有都显示为 0.意味着在弹出期间进度是 34%,在UI中将它的0%显示为,但下载正在按常规方式继续。

我的日志也显示完美但用户界面不显示。我尝试了所有的答案。都是同样的问题。

这是我的全部代码:

在 App Delegate 方法中:

CTAppDelegate.h
@property (copy) void (^backgroundSessionCompletionHandler)();
CTAppDelegate.m
- (void)application:(UIApplication *)application handleEventsForBackgroundURLSession:(NSString *)identifier completionHandler:(void (^)())completionHandler
{
 self.backgroundSessionCompletionHandler = completionHandler;
}
2 ndViewController.h
- (IBAction)downloadBackground:(id)sender;
- (IBAction)downloadImage:(id)sender;
@property (strong, nonatomic) IBOutlet UIImageView *downloadedImage;
@property (strong, nonatomic) IBOutlet UIProgressView *progressView;
@end
2 ndViewController.m
#import"CTViewController.h"
#import"CTSessionOperation.h"
#import"CTAppDelegate.h"
static NSString *downloadUrl = @"http://www.nasa.gov/sites/default/files/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 <Foundation/Foundation.h>
 typedef void (^CTProgressBlock)(double totalBytesWritten, double bytesExpected);
 typedef void (^CTCompletionBlock)(NSURL *imageUrl, BOOL success);
 @interface CTSessionOperation : NSOperation<NSURLSessionDelegate, NSURLSessionTaskDelegate, NSURLSessionDownloadDelegate>
 @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

这是我的完整代码。请用这个核对。: )

时间:原作者:0个回答

133 3

我将与你做的事情有点不同:)

下面是我处理它的方法:

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

2.Declare 在NSOpertaion类中的协议,它将通知当前下载状态,以确认这里协议的任何人

3.In 你的第二个VC启动NSOpertaion并选择委托:) 并相应地更新你的进度

  • 在viewWillDisappear中删除它作为委托,并将它的作为委托添加到secondVC中的NSOperation中

下面是一些相同的代码:)

downloadAssets.h

#import <Foundation/Foundation.h>
@protocol AssetDownloadStatusProtocol <NSObject>
-(void)updateStatusWithValue:(float) progress;
@end
@interface downloadAssets : NSOperation
@property (nonatomic,weak) id<AssetDownloadStatusProtocol> 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 <AssetDownloadStatusProtocol>

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 = 操作;

免责声明

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

简单的对吧有疑问,): ) 快乐编码?

原作者:
...