我对异步编程的概念很陌生,但我得到了它的一般要点(事情在后台运行)。
我遇到的问题是我有一种利用AFNetworking 2.0发出HTTP帖子请求的方法,它在大多数情况下都有效。
但是,我无法弄清楚如何在方法返回时让方法实际返回从响应中接收的值,然后THEN从响应中获取值。
-(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!
}
什么是正确的'处理这种情况的方法?我听过使用“回调”的耳语,但在这种情况下,我真的不明白如何实现这一点。
任何指导或帮助都会很棒,欢呼!
答案 0 :(得分:1)
问题在于,POST
异步运行,正如您所指出的那样,所以在实际return
属性之前,您正在点击responseValue
行设置,因为success
块稍后运行。在其中放置断点/ 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
财产,因为现在您正在使用完成功能块,您可以通过该机制将其传回给您,而不是依靠在类属性上。
答案 1 :(得分:1)