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

时间:2014-02-12 21:14:41

标签: ios objective-c nsarray afnetworking

我已经创建了一个使用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

3 个答案:

答案 0 :(得分:2)

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);

 }];

答案 1 :(得分:2)

由于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

答案 2 :(得分:1)

除了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);
}

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

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