1

以下方法使用 AFNetworking 向 Web 服务发送请求并(成功时)对响应进行操作。AFNetworking 异步执行请求并使用块来判断成功或失败。所以发送请求的方法看起来像这样(简化):

- (void)sendRequestForConnector:(NSString *)connector 
          success:(void (^)(NSData *responseXml))success
          failure:(void (^)(NSError *error))failure
{
  AFHTTPRequestOperation *operation = [self HTTPRequestOperationForConnector:connector];
  [operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) 
  {
    [self handleSuccessForConnector:connector response:[operation responseData]];
    success([operation responseData]);
  } 
  failure:^(AFHTTPRequestOperation *operation, NSError *error) 
  {
    [self handleFailureForConnector:connector error:error];
    failure(error);
  }

  [operation start];
}

在另一个类中,此方法用于多次调用 Web 服务。上一个调用成功后,下一个调用就完成了。这个方法看起来像这样(为简洁起见省略了故障块):

- (void)import 
{
   [client sendRequestForConnector:@"cities" success:^{
     [client sendRequestForConnector:@"categories" success:^{
       [client sendRequestForConnector:@"categoryTranslations" success:^{
         [client sendRequestForConnector:@"products" success:^{
           [client sendRequestForConnector:@"productTranslations" success:^{

             [self finishImport];

           }];
         }];
       }]; 
     }];
   }];
}

这是可行的,但是正如我们所看到的,每个 web 服务调用都会添加另一个嵌套的成功块处理程序。在我看来,必须有更好的方法来做到这一点,但我想不出一个。

最好,我想在执行下一个调用之前等待上一个调用完成,并使用 GCD 之类的东西异步调用整个导入方法。然而,AFNetworking 并不是为进行同步调用而设计的。

任何如何实现这一目标的想法都非常受欢迎。还是我目前的解决方案是可行的?

4

5 回答 5

3

我处于同样的情况,我需要等待响应并需要在完成最后一次上传后调用 ws 进行上传,

做这件事有很多种方法

1)您可以使用dispatch_group并在完成所有操作时通知。

2)用create semaphores一一调用ws

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

dispatch_async(queue, ^{
    dispatch_semaphore_t test = dispatch_semaphore_create(0);
    for (NSUInteger i = 0; i < self.uploadDocument.count; ++i) {
       // My custom method with block which call ws 
      [self uploadMultipleImagesUsingAFNetworkingMultipartFormatWithDocumentId:[[self.uploadDocument objectAtIndex:i] valueForKey:kDocument_DocumentId] andIndex:i withCompletionBlock:^(id responseObj, NSError *error) {

            // Your Logic 

            dispatch_semaphore_signal(test);
        }];
        dispatch_semaphore_wait(test, DISPATCH_TIME_FOREVER);

    // Here comes when your all ws finish 
      dispatch_async(dispatch_get_main_queue(), ^{
              [self.tblUpload reloadData];
              [UIApplication sharedApplication].networkActivityIndicatorVisible = NO;

        });
    }
于 2016-07-01T04:43:52.050 回答
1

你可以看看octokit。他们将 AFNetworking 与 Mantle 和 ReactiveCocoa 结合在一起 - 链式与 ReactiveCocoa 一起工作起来轻松而干净。

https://github.com/octokit/octokit.objc

于 2014-03-20T17:49:16.180 回答
0

我建议你看看这个答案Better asynchronous control flow with Objective-C blocks

建议使用一些自定义解决方案来解决此问题。

于 2013-10-24T12:51:51.463 回答
0

我面临同样的问题,并且一直在考虑引入PromiseKitAFNetworking-PromiseKit一段时间。但我最终放弃了,想出了一个简单而有点杂乱无章的解决方案,

所以我引入了一个叫“step”的属性,主要目的是为了kvo它。然后对于每个异步调用,当它完成时,它需要标记它的步骤。然后kvo 方法将整个过程移至下一步,即kvo 方法进行流控制。

例如,您的 sendRequestForConnector:@"cities" 将是第 1 步,@"categories" 是第 2 步,@"categoryTranslations" 是第 3 步,@"products" 是第 4 步 ...在每个成功块的末尾设置走向自己的价值。所以 kvo 会知道这一步已经完成,它需要调用下一个异步方法。

kvo 方法监督和控制整个过程。

switch (step.intValue) {
    case 1: //call step2; break;
    case 2: //call step3; break;
    case 3: //call step4; break;
    case 4: //call step5; break;
    ...
    case x: // finish, remove kvo on step
}

到目前为止,它符合我的目的,我的代码看起来确实更干净。

于 2016-07-01T04:34:10.997 回答
-2

如果你想进行同步调用,那么只需使用 NSString 的“stringWithContentsOfURL:”方法。因此,只需在循环中使用此代码循环遍历 NSURL 的 NSArray。

NSError* error = nil;
NSString* htmlSource = [NSString stringWithContentsOfURL:theNSURL encoding:NSUTF8StringEncoding error:&error];
if (error) {
    // handle error
}
// parse htmlSource
于 2012-11-21T11:26:14.697 回答