49

因此,我正在使用 AFNetworking 2.0 为 iOS 7 重写一个应用程序,并且遇到了一次发送一批请求并跟踪其进度的问题。在旧的 AFNetworking 中有enqueueBatchOfHTTPRequestOperations:progressBlock:completionBlock:方法 on AFHTTPClient,这显然被重构了,我对如何将多个请求排队有点困惑。

我创建了一个子类,AFHTTPSessionManager并使用POST:...andGET:...方法与服务器进行通信。但是我在代码和/或文档中找不到任何东西可以像旧的AFHTTPClient.

我唯一能找到的是 上未记录的batchOfRequestOperations:progressBlock:completionBlock:方法AFURLConnectionOperation,但这看起来像是 iOS 6 的做法。

显然,我在新NSURLSession概念中遗漏了一些东西,我应该用它来批处理请求或查看新的 AFNetworking 功能。希望有人可以在这里帮助我走上正确的道路!

tl;dr:如何用我的AFHTTPSessionManager子类发送一批请求?

4

5 回答 5

85

感谢 Sendoa 提供指向GitHub 问题的链接,Mattt 解释了为什么此功能不再起作用。有一个明确的原因表明新NSURLSession结构不可能做到这一点;任务不是操作,因此使用依赖项或批量操作的旧方法将不起作用。

我已经创建了这个解决方案dispatch_group,它可以使用 批处理请求NSURLSession,这里是(伪)代码:

// Create a dispatch group
dispatch_group_t group = dispatch_group_create();

for (int i = 0; i < 10; i++) {
    // Enter the group for each request we create
    dispatch_group_enter(group);

    // Fire the request
    [self GET:@"endpoint.json"
       parameters:nil
          success:^(NSURLSessionDataTask *task, id responseObject) {
                  // Leave the group as soon as the request succeeded
                  dispatch_group_leave(group);
          }
      failure:^(NSURLSessionDataTask *task, NSError *error) {
                  // Leave the group as soon as the request failed
                  dispatch_group_leave(group);
              }];
}

// Here we wait for all the requests to finish
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
    // Do whatever you need to do when all requests are finished
});

我想写一些让这更容易做的东西,并与马特讨论这是否是可以合并到 AFNetworking 中的东西(如果实现得很好)。在我看来,用图书馆本身做这样的事情会很棒。但是我必须检查一下我什么时候有空闲时间。

于 2013-11-09T21:35:32.210 回答
3

只是更新线程......我遇到了同样的问题,经过一些研究,我找到了一些好的解决方案,但我决定坚持这个:

我正在使用名为Bolts的项目。因此,对于@Mac_Cain13 发布的上述相同示例,它将是:

[[BFTask taskWithResult:nil] continueWithBlock:^id(BFTask *task) {
    BFTask *task = [BFTask taskWithResult:nil];
    for (int i = 0; i < 10; i++) {
        task = [task continueWithBlock:^id(BFTask *task) {
            return [self executeEndPointAsync];
        }];
    }
    return task;
}] continueWithBlock:^id(BFTask *task) {
    // Everything was executed.
    return nil;
}];;

- (BFTask *) executeEndPointAsync {
    BFTaskCompletionSource *task = [BFTaskCompletionSource taskCompletionSource];
    [self GET:@"endpoint.json" parameters:nil
      success:^(NSURLSessionDataTask *task, id responseObject) {
        [task setResult:responseObject];
      }
      failure:^(NSURLSessionDataTask *task, NSError *error) {
        [task setError:error];
      }];
    }];
    return task.task;
}

基本上,它堆叠所有的任务,等待和解包,直到没有更多的任务,并且在一切都完成后执行最后一个完成块。

另一个做同样事情的项目是 RXPromise,但对我来说,Bolts中的代码更清晰。

于 2014-12-09T07:41:36.983 回答
3

对于request可以是postget,您可以AFNetworking 2.0用于批处理操作,因为首先您需要创建这样的操作:

//Request 1
NSString *strURL = [NSString stringWithFormat:@"your url here"];
NSLog(@"scheduleurl : %@",strURL);
NSDictionary *dictParameters = your parameters here
NSMutableURLRequest *request = [[AFHTTPRequestSerializer serializer] requestWithMethod:@"POST" URLString:strURL parameters:dictParameters error: nil];

AFHTTPRequestOperation *operationOne = [[AFHTTPRequestOperation alloc] initWithRequest:request];
operationOne = [AFHTTPResponseSerializer serializer];

[operationOne setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject)
{
     //do something on completion
} 
failure:^(AFHTTPRequestOperation *operation, NSError *error)
{
     NSLog(@"%@",[error description]);
}];

//Request 2
NSString *strURL1 = [NSString stringWithFormat:@"your url here"];
NSLog(@"scheduleurl : %@",strURL);
NSDictionary *dictParameters1 = your parameters here
NSMutableURLRequest *request1 = [[AFHTTPRequestSerializer serializer] requestWithMethod:@"POST" URLString:strURL1 parameters:dictParameters1 error: nil];

AFHTTPRequestOperation *operationTwo = [[AFHTTPRequestOperation alloc] initWithRequest:request1];
operationTwo = [AFHTTPResponseSerializer serializer];

[operationTwo setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject)
{
     //do something on completion
} 
failure:^(AFHTTPRequestOperation *operation, NSError *error)
{
     NSLog(@"%@",[error description]);
}];

//Request more here if any

现在执行这样的批处理操作:

//Batch operation
//Add all operation here 
NSArray *operations = [AFURLConnectionOperation batchOfRequestOperations:@[operationOne,operationTwo] progressBlock:^(NSUInteger numberOfFinishedOperations, NSUInteger totalNumberOfOperations)
{
    NSLog(@"%i of %i complete",numberOfFinishedOperations,totalNumberOfOperations);
    //set progress here
    yourProgressView.progress = (float)numberOfFinishedOperations/(float)totalNumberOfOperations;

} completionBlock:^(NSArray *operations) 
{
    NSLog(@"All operations in batch complete");
}];

[[NSOperationQueue mainQueue] addOperations:operations waitUntilFinished:NO];
于 2015-05-20T07:01:07.783 回答
1

在 AFNetworking 2.0 上,AFHTTPClient已拆分为AFHTTPRequestOperationManagerand AFHTTPSessionManager,因此您可能可以从第一个开始,它具有operationQueue属性。

于 2013-11-05T02:16:54.833 回答
1

目前,NSURLSession任务不适合请求操作使用的同类模式。有关此问题,请参阅 Mattt Thompson 的答案。

直接回答:如果你需要依赖或批处理,你仍然需要使用请求操作。

于 2013-11-05T10:22:37.810 回答