iOS - Passing blocks to functions
afnetworking, iphone, objective-c, objective-c-blocks
Solution
It's awkward until you get used to it. The variable name appears mixed in with the type...
void (^success)(NSURLRequest *, NSHTTPURLResponse *, id) = ^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {
NSLog(@"request is %@, response is %@ and json is %@", request, response, JSON);
};
The stack variable name in this case is success. You can now refer to it in subsequent expressions that take the same type, like ...
AFJSONRequestOperation *operation = [AFJSONRequestOperationJSONRequestOperationWithRequest:request
success:success];
You can also make a block an property, like this:
@property (copy, nonatomic) void (^success)(NSURLRequest *, NSHTTPURLResponse *, id);
And call it like this:
self.success(aRequest, aResponse, someJSON);
Remember to nil it out when you're done calling it, so the caller has less to worry about creating a retain cycle.
Edit: good suggestion in commentary about using typedef to make this easier on the eyes and fingers:
typedef void (^SuccesBlock)(NSURLRequest *, NSHTTPURLResponse *, id);
So the stack variable looks like this:
SuccessBlock success = ^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {
NSLog(@"request is %@, response is %@ and json is %@", request, response, JSON);
};
and the property looks like this:
@property (copy, nonatomic) SuccessBlock success;
Problem
I have a method call (it's a call from AFNetworking): ``` AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) { NSLog(@"IP Address: %@", [JSON valueForKeyPath:@"origin"]); } failure:^(NSURLRequest *request , NSURLResponse *response , NSError *error , id JSON) { NSLog(@"Failed: %@",[error localizedDescription]); }]; ``` and I'm trying to pull the sucess and failure blocks out into a separate variable, that I can later pass into the method. But I can't figure out how to declare the blocks as variables. I'm looking to do something like this: ``` IDontKnowWhatKindOfDataTypeGoesHere successBlock = ^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) { NSLog(@"IP Address: %@", [JSON valueForKeyPath:@"origin"]); } ``` and the same for the failureBlock. So then I'm looking to make the `AFJSONRequestOperation` call like: ``` AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request success:successBlock failure:failureBlock]; ``` But I cant figure how what the data types of the successBlock and failureBlock should be. This is more for organization I suppose. I have a lot of code in my successBlock and the autoformatting of Xcode pushes is all to the right side of the screen which is totally annoying. So if I can pull it out (which should be possible, right), then I can organize my code better. Thanks!