Reputation: 15365
I hate blocks. They are meant to make the code more concise, but I couldn't find anything more ugly. For instance, with AFNetworking:
AFJSONRequestOperation* operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request
requestsuccess:^(NSURLRequest *request, NSURLResponse *response, id JSON) {
// Some
// very
// long
// (and as ugly as blocks)
// processing
}
failure:^(NSURLRequest *request, NSURLResponse *response, NSError *error, id JSON )) {
// Failure code
}]
Something like this would have been much better:
AFJSONRequestOperation* operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request
requestsuccess:@selector(requestSuccess:response:json:)
failure:@selector(requestSuccess:response:error:)]
So, is it possible to use method's selectors as blocks ? If not, how can I make the block code better ?
It annoys me, as these blocks seems to be the future of objective-c programming and they are just NOT readable.
Upvotes: 11
Views: 5451
Reputation: 53000
Short blocks are good, overly long ones not, where you draw the line is of course a personal preference...
Using a method for a block is not hard (the other way around is more of a challenge). The simplest approach if you wish to use a method:
- (void) requestSuccess:(NSURLRequest *)request
response:(NSURLResponse *)response
json:(id)JSON
{
// Some
// very
// long
// (and as ugly as blocks)
// processing
}
- (void) requestFailure:(NSURLRequest *)request
response:(NSURLResponse *)response
error:(NSError **)error
json:(id)JSON
{
// Failure code
}
...
AFJSONRequestOperation* operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request
requestsuccess:^(NSURLRequest *request, NSURLResponse *response, id JSON)
{
[self requestSuccess:request response:response json:JSON];
}
failure:^(NSURLRequest *request, NSURLResponse *response, NSError *error, id JSON ))
{
[self requestFailure:request response:response error:error json:JSON];
}]
You could go further with macros, or even performSelector
/NSInvocation
fun - whether it is worth it is up to you.
You can also move the blocks definitions before the call itself, along the lines of:
var = block;
[object method:var];
Which approach you choose is a matter of style.
Upvotes: 2
Reputation: 35384
So you think the block construct makes the code harder to read? I think they can sometimes make things easier to understand, especially in asynchronous contexts like in networking code.
To make it easier to read you can assign blocks to variables. (Indeed blocks are objective-c objects.)
Example:
typedef void(^SuccessBlock)(NSURLRequest *request, NSURLResponse *response, id JSON);
SuccessBlock successBlock = ^(NSURLRequest *request, NSURLResponse *response, id JSON) {
// code block
};
AFJSONRequestOperation* operation;
operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request
success:successBlock
failure:nil];
You can also call a single handler method inside the block to keep it small.
Upvotes: 7
Reputation: 5703
You can peel out the blocks so they're not in-line parameters to method calls. It still involves a bit of block ugliness, but still improves readability some:
void (^successBlock)(NSURLRequest *request, NSHTTPURLResponse *response, id JSON);
successBlock = ^ (NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {
// Some
// very
// long
// (and as ugly as blocks)
// processing
};
//do same for failure block as "failureBlock"
...
AFJSONRequestOperation* operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request
requestsuccess:successBlock
failure:failureBlock];
Upvotes: 1