AFNetworking Array在块内返回JSON但不在块外部

我已经创建了一个使用AFNetworking API返回JSON数据的自定义方法。

我正在尝试将从我的Web服务中提取的数据存储在一个数组中作为JSON。 NSLog(@“%@”,json); 块内部将JSON数据打印到控制台。 块NSLog外部(@“%@”,json); 返回null。 这是为什么以及如何解决?

我想要做的是获取返回JSON数据的方法(NSArray)

#import "WebService.h" #import "AFNetworking.h" #import "MBProgressHUD.h" @implementation WebService - (NSArray *)postRequest:(NSDictionary *)postParameters { //MBProgressHUD *progressHUD = [MBProgressHUD showHUDAddedTo:self.view animated:YES]; //progressHUD.labelText = @"Loading"; __block NSArray *json; AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager]; [manager POST:@"http://192.168.0.100/app.php" parameters:postParameters success:^(AFHTTPRequestOperation *operation, id responseObject) { NSString *responseString = [operation responseString]; NSError *error; json = [NSJSONSerialization JSONObjectWithData:[responseString dataUsingEncoding:NSUTF8StringEncoding] options:kNilOptions error:&error]; NSLog(@"%@", json); // RETURNS JSON } failure:^(AFHTTPRequestOperation *operation, NSError *error) { UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Network Unavailable" message:@"Unable to contact server. Please try again later." delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil]; [alert show]; NSLog(@"Error: %@", error); }]; NSLog(@"%@", json); // RETURNS NULL return json; } @end 

POST方法是异步的。 意味着该块转到单独的线程并等待执行。 虽然这是背景,但其余代码仍在继续,好像什么也没发生。 因此它立即获得NSLog语句(可能在开始POST请求之前)。

如果您希望块外的json对象,您将不得不从块内部发送到您选择的方法并继续在那里进行操作。

 [manager POST:@"http://192.168.0.100/app.php" parameters:postParameters success:^(AFHTTPRequestOperation *operation, id responseObject) { NSString *responseString = [operation responseString]; NSError *error; json = [NSJSONSerialization JSONObjectWithData:[responseString dataUsingEncoding:NSUTF8StringEncoding] options:kNilOptions error:&error]; NSLog(@"%@", json); // RETURNS JSON dispatch_async(dispatch_get_main_queue(), ^{ [self doSomethingWithJson:json]; }); } failure:^(AFHTTPRequestOperation *operation, NSError *error) { UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Network Unavailable" message:@"Unable to contact server. Please try again later." delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil]; [alert show]; NSLog(@"Error: %@", error); }]; 

由于POST以异步方式运行,因此无法返回结果。 但是您可以使用与AFNetworking相同的完成块模式:

 - (void) postRequest:(NSDictionary *)postParameters success:(void (^)(id jsonObject))success failure:(void (^)(NSError *error))failure { AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager]; [manager POST:@"http://192.168.0.100/app.php" parameters:postParameters success:^(AFHTTPRequestOperation *operation, id responseObject) { if (success) success(responseObject); } failure:^(AFHTTPRequestOperation *operation, NSError *error) { UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Network Unavailable" message:@"Unable to contact server. Please try again later." delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil]; [alert show]; if (failure) failure(error); }]; } 

你称之为:

 [self postRequest:postParameters success:^(id jsonObject) { NSLog(@"json = %@", jsonObject); } failure:^(NSError *error) { NSLog(@"error = %@", error); }]; 

请注意,我已经大大简化了代码,因为您不必执行JSON解析,因为AFNetworking已经为您执行了此操作(因为默认的responseSerializerAFJSONResponseSerializer )。 正如您所看到的,您的上述方法没有比标准AFNetworking POST方法做得更多,如果出现错误,它会显示UIAlertView

除了wat @ Putz1103说,你可以使用回调方法,这也是一种在JavaScript中使用的技术。

例:

 [manager POST:@"http://192.168.0.100/app.php" parameters:postParameters success:^(AFHTTPRequestOperation *operation, id responseObject) { NSString *responseString = [operation responseString]; NSError *error; json = [NSJSONSerialization JSONObjectWithData:[responseString dataUsingEncoding:NSUTF8StringEncoding] options:kNilOptions error:&error]; NSLog(@"%@", json); // RETURNS JSON [self dataRetrievedWithData:json]; } failure:^(AFHTTPRequestOperation *operation, NSError *error) { UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Network Unavailable" message:@"Unable to contact server. Please try again later." delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil]; [alert show]; NSLog(@"Error: %@", error); }]; 

然后你会有一个像这样的方法:

 - (void)dataRetrievedWithData:(id)data { NSLog(@"Here's the data.. do what you want to do with the data here. %@", data); } 

在最后一个方法中,您可以添加逻辑以在请求成功完成时执行。 从块返回是不可行的,因为块是在单独的线程上执行的。

该操作是异步的,这意味着您可以在响应到达后简单地打印出来。 异步意味着它在一个单独的线程中运行,因此您必须等待响应才能对响应执行任何操作。