Return value for function inside a block
Asked Answered
V

3

13

I am using AFNetworking to get data from a server:

-(NSArray)some function {
    AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request
        success: ^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {
            NSArray *jsonArray =[JSON valueForKey:@"posts"];
        }
        failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON) {}
}

So what I am trying to do here is to return the jsonArray to the function. Obviously return is not working.

Vauntcourier answered 14/7, 2013 at 18:49 Comment(3)
You can't do this. Since you are dealing with an asynchronous call, your some function method will return long before there is a value to return.Cas
I suggest you take a step back and think about what your code does. You will soon realize that what you want does not make sense.Offering
you can pass blocks to function which will execute on success or error.Hong
M
19

You can't use the completion Block to create a return value for your method. The AFJSONRequestOperation does its work asynchronously. someFunction is going to return while the operation is still working. The success and failure Blocks are how you get resulting values where they need to go.

One option here is to pass in the caller as an argument to your wrapper method so that the completion Block can hand the array off.

- (void)goFetch:(id)caller
{
    AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request
    success: ^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {

        [caller takeThisArrayAndShoveIt:[JSON valueForKey:@"posts"]];
    }
    failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON) {}
}

You could also make your caller create and pass a Block to be run on success. Then goFetch: no longer needs to know what properties exist on the caller.

- (void)goFetch:(void(^)(NSArray *))completion
{
    AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request
    success: ^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {
        if( completion ) completion([JSON valueForKey:@"posts"]);
    }
    failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON) {}
}
Mazzola answered 14/7, 2013 at 19:7 Comment(0)
T
3

As others have said, you can't do that when dealing with async call. Instead of returning the expected Array, you could pass a completion block as a parameter

typedef void (^Completion)(NSArray* array, NSError *error);

-(void)someFunctionWithBlock:(Completion)block {
    AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request
        success: ^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {
            NSArray *jsonArray =[JSON valueForKey:@"posts"];
            if (block) block(jsonArray, nil);
        }
        failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON) { 
            if (block) block(nil, error); 
        }
}

Then where you call that someFunction. This code will also do proper error handling for you.

[yourClassInstance someFunctionWithBlock:^(NSArray* array, NSError *error) {
   if (error) {
      NSLog(%@"Oops error: %@",error.localizedDescription);
   } else {
      //do what you want with the returned array here.
   }
}];
Tims answered 1/8, 2015 at 23:25 Comment(0)
A
0

i faced this kind of problem and solve it by this method below. I saw the answers above using blocks. But this solution was more suitable for at that time. Logic of the method is simple. You need to send the object and its method as a parameter and after request finished that method will be called. Hope it helps.

+(void)request:(NSString *)link parameters:(NSDictionary *)params  forInstance:(id)instance returns:(SEL)returnValue
{
    AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
    [manager GET:link
      parameters:params
         success:^(AFHTTPRequestOperation *operation, id responseObject)
     {
         [instance performSelector:returnValue withObject: responseObject];
     }
         failure:^(AFHTTPRequestOperation *operation, NSError *error)
     {
         [instance performSelector:returnValue withObject:nil];
         //NSLog(@"Error: %@", error);
     }];
}
Advection answered 1/8, 2015 at 23:42 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.