AFNetworking。检查所有操作队列的下载进度 [英] AFNetworking. Check download progress for all operation queue

查看:148
本文介绍了AFNetworking。检查所有操作队列的下载进度的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个使用AFNetworking制作的iOS应用程序。
我有一个单例自定义httpclient子类,我用它来消耗我的api并从服务器下载二进制文件。

I have an iOS application made with AFNetworking. I have a singleton custom httpclient subclass and i use it to consume my api and download binary files from server.

我需要下载约100个文件。遍历我的URL数组并为每个URL创建一个AFHTTPRequestionOperation是否安全?我的代码是这样的:

I need to dowload about 100 files. Is it safe to iterate trough my url array and create one AFHTTPRequestionOperation for each url? My code is this:

NSMutableURLRequest* rq = [[MIHTTPClient sharedInstance] requestWithMethod:@"GET" path:@"...." parameters:nil];
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:rq] ;
operation.outputStream = [NSOutputStream outputStreamToFileAtPath:path append:NO];

[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
    //completion

} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
    //manage error
}];


[[MIHTTPClient sharedInstance] enqueueHTTPRequestOperation:operation];

如何从此队列中获得反馈?我没有看到任何 HTTPClientDelegate协议或类似的东西。

How can I receive a feedback from this queue? i don't see any "HTTPClientDelegate" protocol or something like this.

推荐答案

关于进度,请参见 setDownloadProgressBlock (是 AFURLConnectionOperation 的一部分,从中将 AFHTTPRequestOperation 子类化),例如:

Regarding progress, see setDownloadProgressBlock (part of AFURLConnectionOperation, from which AFHTTPRequestOperation is subclassed), e.g.:

[operation setDownloadProgressBlock:^(NSInteger bytesWritten, NSInteger totalBytesWritten, NSInteger totalBytesExpectedToWrite) {
    NSLog(@"Sent %d of %d bytes, %@", totalBytesWritten, totalBytesExpectedToWrite, path);
}];

然后,在代码示例中,您调用 setCompletionBlockWithSuccess:failure: ,以便提供有关单个操作完成的状态。就个人而言,在我的小测试中,我只是维护了我请求的下载的数组,并通过以下三个块(进度,成功和失败)来更新下载的状态码,如下所示:

And, in your code sample, you're calling setCompletionBlockWithSuccess:failure:, so that provides the status regarding the completion of the individual operations. Personally, in my little test, I just maintain an array of my requested downloads, and have these three blocks (progress, success, and failure) update the status code of my downloads like so:

for (NSInteger i = 0; i < 20; i++)
{
    NSURLRequest *request = ... // set the request accordingly

    // create a download object to keep track of the status of my download

    DownloadObject *object = [[DownloadObject alloc] init];
    download.title = [NSString stringWithFormat:@"Download %d", i];
    download.status = kDownloadObjectStatusNotStarted;
    [self.downloadObjects addObject:download];

    AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];

    [operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
        download.status = kDownloadObjectStatusDoneSucceeded;

        // update my UI, for example, I have table view with one row per download
        //
        // [self.tableView reloadRowsAtIndexPaths:@[[NSIndexPath indexPathForRow:i inSection:0]]
        //                       withRowAnimation:UITableViewRowAnimationNone];
    } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
        download.status = kDownloadObjectStatusDoneFailed;

        // update UI
        //
        // [self.tableView reloadRowsAtIndexPaths:@[[NSIndexPath indexPathForRow:i inSection:0]]
        //                       withRowAnimation:UITableViewRowAnimationNone];
    }];

    [operation setDownloadProgressBlock:^(NSUInteger bytesRead, long long totalBytesRead, long long totalBytesExpectedToRead) {
        download.totalBytesRead = totalBytesRead;
        download.status = kDownloadObjectStatusInProgress;

        // update UI
        //
        // [self.tableView reloadRowsAtIndexPaths:@[[NSIndexPath indexPathForRow:i inSection:0]]
        //                       withRowAnimation:UITableViewRowAnimationNone];
    }];

    [queue addOperation:operation];
}

您可以通过这种方式跟踪各个下载。您还可以仅跟踪挂起的操作(或查询 HTTPClient 对象的 operationQueue 属性,然后查看 operationCount 属性)。

You can keep track of the individual downloads this way. You can also just keep track of the pending operations (or query the HTTPClient object's operationQueue property, and look at the operationCount property of that).

在下载100个文件方面,有两个注意事项:

In terms of downloading 100 files, two considerations:


  • 我本以为您想调用 setMaxConcurrentOperationCount HTTPClient 子类的 operationQueue 上的c $ c>,将其设置为某个合理的数字(4或5),看看AFNetworking代码,似乎并没有这样做。我发现,如果超出此范围,回报就会递减,并且如果所有文件都来自一台服务器,则在给定客户端和给定服务器之间可以执行多少并发操作受到限制。

  • I would have thought that you'd want to call setMaxConcurrentOperationCount on the operationQueue of your HTTPClient subclass, setting it to some reasonable number (4 or 5), as glancing at the AFNetworking code, it doesn't seem to do that. I find that there are diminishing returns if you go much above that, and if all of the files are from a single server, there are constraints on how many concurrent operations can be done between a given client and given server.

我读过一些传闻,称苹果将拒绝通过蜂窝网络提出非常规请求的应用程序。参见 https://stackoverflow.com/a/14922807/1271826

I've read anecdotal claims that the Apple will reject apps that make extraordinary requests over cellular network. See https://stackoverflow.com/a/14922807/1271826.

这篇关于AFNetworking。检查所有操作队列的下载进度的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆