iOS - Passing blocks to functions

人盡茶涼 提交于 2020-01-01 15:56:13

问题


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!


回答1:


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;


来源:https://stackoverflow.com/questions/18220645/ios-passing-blocks-to-functions

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!