I have a method that does an asynchronous network call, and then passes the success or failure results back via blocks:
- (void) loginWithSuccess:(void (^)(id responseObject))success failure:(void (^)(NSError* error))failure {
...
if(error) {
failure(error);
}
else {
success(responseObject);
}
}
I noticed that if I call this method and pass in nil
as my blocks, my application will crash with EXEC_BAD_ACCESS
:
[manager loginWithWithSuccess:nil failure:nil];
But, if I pass in empty blocks, it runs fine:
[manager loginWithWithSuccess:^(id responseObject){} failure:^(NSError *error){}];
I assume this is because at runtime you can't pass parameters to nil
? So, when defining my methods that take blocks, should I always check that the blocks are not nil before calling them?
Just looking at Apple's Frameworks, some methods with block parameters accept NULL/nil
as the block argument (e.g. animateWithDuration:animations:completion:
), others don't (e.g. enumerateObjectsUsingBlock:
).
If you're designing an API, you have to make that decision. If it makes sense to not have a block, you should accept nil
and check before executing the block, otherwise you should throw an assertion like [@[] enumerateObjectsUsingBlock:nil]
does:
'NSInvalidArgumentException', reason: '*** -[NSArray enumerateObjectsUsingBlock:]: block cannot be nil'
EXEC_BAD_ACCESS
?When invoking a block you are dereferencing the address, which you obviously can't do if it's not pointing to an actual block. There is a great explanation in this answer.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With