处理AFNetworking2.0异步HTTP请求

Posted

技术标签:

【中文标题】处理AFNetworking2.0异步HTTP请求【英文标题】:Dealing with AFNetworking2.0 asynchronous HTTP request 【发布时间】:2014-04-08 23:18:17 【问题描述】:

我对异步编程的概念非常陌生,但我了解它的一般要点(事情在后台运行)。

我遇到的问题是我有一种利用 AFNetworking 2.0 发出 HTTP 发布请求的方法,并且它在大多数情况下都有效。

但是,我无法弄清楚如何让该方法在方法返回时实际返回从响应中接收到的值,然后从响应中获取值。

-(int) registerUser

self.responseValue = 000; //Notice I set this to 000 at start of method

AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
manager.requestSerializer = [AFJSONRequestSerializer serializer];

NSDictionary *parameters = @ @"Username": @"SomeUsername" ;

[manager POST:@"http://XXX/register"
   parameters:parameters
      success:^(AFHTTPRequestOperation *operation, id responseObject)
 
     NSLog(@"JSON: %@", responseObject);
     NSError *err = nil;

     self.responseValue = [[responseObject objectForKey:@"res"] intValue]; 
     //Note: This^ value returns 99 and NSLogs confirm this
 
      failure:^(AFHTTPRequestOperation *operation, NSError *err)
 
     NSLog(@"Error: %@", err);
 ];

return self.responseValue; //This will return 000 and never 99!

处理这种情况的“正确”方法是什么?我听说过使用“回调”的耳语,但我真的不明白如何在这种情况下实现它。

任何指导或帮助都会很棒,干杯!

【问题讨论】:

Getting variable from the inside of block 的可能重复项 【参考方案1】:

问题在于POST 异步运行,正如您所指出的,所以您在return 行中很好地responseValue 属性实际上已设置,因为@987654324 @block 稍后运行。将断点/NSLog 语句放在那里,你会看到你首先点击了return 行。

您通常不会 return 来自异步方法的值,而是采用完成块模式。例如:

- (void)registerUserWithCompletion:(void (^)(int responseValue, NSError *error))completion

    AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
    manager.requestSerializer = [AFJSONRequestSerializer serializer];

    NSDictionary *parameters = @ @"Username": @"SomeUsername" ;

    [manager POST:@"http://XXX/register"
       parameters:parameters
          success:^(AFHTTPRequestOperation *operation, id responseObject)
     
         NSLog(@"JSON: %@", responseObject);

         int responseValue = [[responseObject objectForKey:@"res"] intValue];

         if (completion)
             completion(responseValue, nil);
     
          failure:^(AFHTTPRequestOperation *operation, NSError *err)
     
          NSLog(@"Error: %@", err);

          if (completion)
             completion(-1, err); // I don't know what you want to return if it failed, but handle it appropriately
    ];

然后,您可以按如下方式使用它:

[self registerUserWithCompletion:^(int responseValue, NSError *error) 
    if (error)
        NSLog(@"%s: registerUserWithCompletion error: %@", __FUNCTION__, error);
    else
        NSLog(@"%d", responseValue);

    // do whatever you want with that responseValue here, inside the block
];

// Needless to say, don't try to use the `responseValue` here, because
// `registerUserWithCompletion` runs asynchronously, and you will probably
// hit this line of code well before the above block is executed. Anything
// that is dependent upon the registration must called from within the above
// completion block, not here after the block.

请注意,我建议您停用您之前拥有的 responseValue 属性,因为现在您正在使用完成块,您可以通过该机制将其传递给您,而不是依赖于类属性。

【讨论】:

很好的答案,谢谢。当我回到家时,我会试一试——我已经阅读了一些关于完成块的内容,我想我明白了:)【参考方案2】:

检查这个并使用搜索;-))

Getting variable from the inside of block

已经有很多重复了!

:-)

【讨论】:

以上是关于处理AFNetworking2.0异步HTTP请求的主要内容,如果未能解决你的问题,请参考以下文章

AFNetworking 2.0 多部分请求正文空白

AFNetworking2.0源码解析<二>

异步处理http请求同步返回结果

(05)使用DeferredResult多线程异步处理请求

(05)使用DeferredResult多线程异步处理请求

angularjs $q$http 处理多个异步请求