0

I want to get some data from web service and it works fine bu now I want to store the returned value from a variable from a block, but the variable's value is changed only inside the block and it returns null outside the block, how can I do it ? here is my code:

-(void)getDataFromServer:(NSString *) urlString{
__block id returnedData;
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];

NSURLCredential *credential = [NSURLCredential credentialWithUser:username password:password persistence:NSURLCredentialPersistenceNone];

NSMutableURLRequest *request = [manager.requestSerializer requestWithMethod:@"GET" URLString:urlString parameters:nil];

AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
[operation setCredential:credential];
[operation setResponseSerializer:[AFJSONResponseSerializer alloc]];
[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
   // NSLog(@"Success: %@", responseObject);
    returnedData = responseObject;
    NSLog(@"returned data%@" , returnedData); // here returnedData contains the value that I need to store

} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
    NSLog(@"Failure: %@", error);
} ];

[manager.operationQueue addOperation:operation];
NSLog(@"returned data%@" , returnedData); // here it returns null value !! 
}

1 Answers1

1

The problem is not with access to the variable, it is with the timing.

Your second NSLog statement is running before the completion block is run. The operation runs asynchronously, and you're logging returnedData before it is set in the completion block.

Edit to add an example solution:

One solution would be to create the completion block in your calling class and past into the operation in the getDataFromServer: method.

- (void)getDataFromServer:(NSString *)urlString completion:(void (^)(AFHTTPRequestOperation *operation, id responseObject))completion {
    AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];

    NSURLCredential *credential = [NSURLCredential credentialWithUser:username password:password persistence:NSURLCredentialPersistenceNone];

    NSMutableURLRequest *request = [manager.requestSerializer requestWithMethod:@"GET" URLString:urlString parameters:nil];

    AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
    [operation setCredential:credential];
    [operation setResponseSerializer:[AFJSONResponseSerializer alloc]];
    [operation setCompletionBlockWithSuccess:completion];

    [manager.operationQueue addOperation:operation];
}
picciano
  • 22,341
  • 9
  • 69
  • 82
  • So what can I do to keep the new value of `returnedData` and to use it outside the block ? – user2389273 Mar 18 '15 at 14:59
  • You can use it outside the block, but you do have to wait for it to be set first. You should probably do something with that value within the completion block. You could call another method, or you could post an NSNotification. What you cannot do is to return a synchronous result from an asynchronous method. – picciano Mar 18 '15 at 15:03
  • I called the method `getDataFromServer`in another class and I declared the `returnedData`as extern variable here is how I called the method : `- (void)viewDidLoad { [super viewDidLoad]; DataViewController *dataViewController = [[DataViewController alloc] init]; [dataViewController getDataFromServer:@"http://firstluxe.com/api/search/search?query=vogue&language=1&output_format=JSON"]; NSLog(@"returned %@ ", returnedData); ` but it is still returning null value, do you have an idea on how to use the new value of this variable? – user2389273 Mar 18 '15 at 15:39
  • You're still trying to use the value **before** it is getting set. See edited answer for one way to do this. – picciano Mar 18 '15 at 15:50
  • I did like this in the second class : - (void)viewDidLoad { [super viewDidLoad]; void (^completion)(AFHTTPRequestOperation* , id) = ^(AFHTTPRequestOperation *operation, id responseObject){ returnedData = responseObject; }; DataViewController *dataViewController = [[DataViewController alloc] init]; [dataViewController getDataFromServer:@"http://firstluxe.com/api/search/search?query=vogue&language=‌​1&output_format=JSON" completion:completion]; NSLog(@"returned %@ ", returnedData); }it returns the new value after the ViewDidload is called for the second time – – user2389273 Mar 19 '15 at 08:47