2014-02-12 2 views
1

AFNetworking API를 사용하여 JSON 데이터를 반환하는 사용자 지정 메서드를 만들었습니다.AFNetworking Array는 블록 내부에서 JSON을 반환하지만 블록 외부에서는 반환하지 않습니다.

내 웹 서비스에서 가져온 데이터를 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 

답변

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

}]; 
+0

어떻게 작동하는지 알 수 있습니다. 내가 뭘 하려는지 JSON 데이터 (NSArray) 반환하는 메서드를 얻는 것입니다. – user2920762

+0

@ user2920762 알아 두십시오. 하지만 우리가 모두 당신에게 말하려고하는 것은 당신이 그렇게해서는 안된다는 것입니다. 메인 큐가 네트워크 요청을 기다리는 것을 결코 원하지 않습니다 (메인 큐를 차단하지 마십시오). JSON 객체를 반환하는'postRequest'를 만드는 유일한 방법은 메인 큐를 차단하고 동기식으로 동작시키는 것입니다. 모든 다양한 대답과 같은 비동기 패턴을 사용하십시오. – Rob

+0

작은 메모 : AFNetworking이 완료 스레드가 주 스레드에서 호출되도록 보장하므로 주 대기열로 디스패치하지 않아도됩니다. –

1

wat @ Putz1103에 추가하여 콜백 메소드를 사용할 수 있습니다. 이것은 자바 스크립트에서도 사용되는 기술입니다.

예 : 요청이 성공적으로 완료되면 실행 로직을 추가 할 수있는 마지막 방법은

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

:

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

}]; 

는 그런 다음 같은 방법을 것이다. 블록이 별도의 스레드에서 실행되기 때문에 블록에서 리턴하는 것은 실제로 가능하지 않습니다.

작업은 비동기식이므로 응답이 도착한 후에 간단히 인쇄 할 수 있습니다. 비동기 란 별도의 스레드에서 실행되므로 응답을 기다리기 전에 응답을 기다릴 필요가 없습니다.

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을 표시합니다.

관련 문제