2013-03-01 53 views
4

我有一个使用AFNetworking制作的iOS应用程序。 我有一个单一的自定义httpclient子类,我用它来消费我的api并从服务器下载二进制文件。AFNetworking。 Сheck下载进度为所有操作队列

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

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”协议或类似的东西。

感谢

回答

5

关于进步,看到setDownloadProgressBlock(的AFURLConnectionOperation一部分,从中AFHTTPRequestOperation的子类),例如:

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

而且,您的代码示例中,你调用setCompletionBlockWithSuccess:failure:,使提供了关于完成单个操作的状态。就个人而言,在我的小测试,我只是保持我的要求下载的数组,并有这三个块(进展,成功和失败)更新我下载的,像这样的状态代码:

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属性)。


在下载100个文件,二方面考虑:

  • 我本来以为你会想打电话setMaxConcurrentOperationCountHTTPClient子类的operationQueue,将其设置为一个合理的数值(4或5),看着AFNetworking代码,似乎没有这样做。我发现,如果你远远高于这个水平,并且如果所有文件都来自单个服务器,那么返回的报酬会递减,但是对于给定客户端和给定服务器之间可以完成多少个并发操作存在限制。

  • 我读过轶事声称苹果将拒绝通过蜂窝网络提出非常请求的应用程序。见https://stackoverflow.com/a/14922807/1271826

+0

setDowloadProgressBlock是有用的单个连接,我用它。我正在为整个队列寻找相同的功能。 感谢setMaxConcurrentOperationCount ... AFN代码将此值设置为NSOperationQueueDefaultMaxConcurrentOperationCount(-1) – IgnazioC 2013-03-01 20:31:06

+1

@IgnazioC是的,我看到他们在哪里设置了'maxConcurrentOperationCount',正因如此,我指出重要的是您需要将它重置为某种比如4或5,如果你打算做100次下载。如果你不这样做,它会同时启动所有的100个操作,而后者最终会超时。设置'maxConcurrentOperationCount'将解决这个问题。进行大量下载时总是非常重要。 – Rob 2013-03-01 23:18:27

+0

在操作的下载进度块和操作的两个完成块之间的“整个队列”的重新进展中,您拥有了所需的一切。您可以跟踪未完成下载的计数,也可以跟踪更新的答案,跟踪单独下载的单独状态。虽然我可以理解你可能想要一个整个队列的状态块,但这是另外三个块的冗余。 – Rob 2013-03-01 23:30:36