我正在使用AFNetworking下载我的应用程序用于同步解决方案的文件.在某些时候,应用程序会将一系列文件下载为批处理单元.
Following this example,我这样运行批次:
NSURL *baseURL = <NSURL with the base of my server>; AFHTTPRequestOperationManager *manager = [[AFHTTPRequestOperationManager alloc] initWithBaseURL:baseURL]; // as per: https://stackoverflow.com/a/19883392/353137 dispatch_group_t group = dispatch_group_create(); for (NSDictionary *changeSet in changeSets) { dispatch_group_enter(group); AFHTTPRequestOperation *operation = [manager POST:@"download" parameters: <my download parameters> success:^(AFHTTPRequestOperation *operation,id responSEObject) { // handle download success... // ... dispatch_group_leave(group); } failure:^(AFHTTPRequestOperation *operation,NSError *error) { // handle failure... // ... dispatch_group_leave(group); }]; [operation start]; } // Here we wait for all the requests to finish dispatch_group_notify(group,dispatch_get_main_queue(),^{ // run code when all files are downloaded });
这对于批量下载是很好的.但是,我想向用户显示一个MBProgressHUD,显示下载是如何进行的.
AFNetworking提供回调方法
[operation setDownloadProgressBlock:^(NSUInteger bytesRead,long long totalBytesRead,long long totalBytesExpectedToRead) { }];
…它可以让您更轻松地更新进度表,只需将进度设置为totalBytesRead / totalBytesExpectedToRead即可.但是,当您同时进行多次下载时,难以全面跟踪.
我已经考虑为每个HTTP操作使用一个带有密钥的NSMutableDictionary,具有以下一般格式:
NSMutableArray *downloadProgress = [NSMutableArray arrayWithArray:@{ @"DownloadID1" : @{ @"totalBytesRead" : @0,@"totalBytesExpected" : @100000},@"DownloadID2" : @{ @"totalBytesRead" : @0,@"totalBytesExpected" : @200000} }];
随着每个操作的下载进程,我可以在中央NSMutableDictionary中更新该特定操作的totalBytesRead,然后总计所有的totalBytesRead和totalBytesExpected“,以得出整个批量操作的总和.然而,AFNetworking的进度回调methoddownloadProgressBlock定义为^(NSUInteger bytesRead,long long totalBytesExpectedToRead){}不包括特定操作作为回调块变量(而不是thesuccessandfailure`回调,其中包含特定操作一个变量,使其可访问).据我所知,这使得它不可能确定哪个操作具体是进行回调.
关于如何使用AFNetworking跟踪多极同时下载进度的任何建议?
解决方法
如果您的块是内联的,则可以直接访问该操作,但是编译器可能会向您提出循环引用.您可以通过声明弱引用来解决问题,并在块内使用它:
__weak AFHTTPRequestOperation weakOp = operation; [operation setDownloadProgressBlock:^(NSUInteger bytesRead,long long totalBytesExpectedToRead) { NSURL* url = weakOp.request.URL; // sender operation's URL }];
实际上,您可以访问该块内的任何内容,但是您需要了解该块的内容.通常,在块创建时,即块被执行的时间,块中所引用的任何变量被复制.这意味着当setDownloadProgressBlock行被执行时,该块中的weakOp将引用weakOp变量的值.你可以认为它就像你在块中引用的每个变量将是如果你的块被立即执行的那样.