Reputation: 28164
I am building a app with many different parts which access remote API calls (both my own, and others). There are many errors that might happen, and to exacerbate the problem, different libraries handle these errors differently.
Essentially, I would like to use the same error handling blocks for all these remote calls.
This is how I would do it with Ruby, but I am not that sure how to manipulate Objective-C in the same manner:
//universal function to handle standard remote errors across errors
def universal_handling
begin
yield
rescue Exception => e
// handle different exceptions accordingly
// allow crash if unexpected exception
end
end
//how I would use the above block
universal_handling{ //any of my remote call here }
So, I have two questions:
I am interested in seeing example code. Error handling can be a major pain, so I want to get this right early on.
Notes:
Upvotes: 1
Views: 565
Reputation: 107754
You can do something very similar with blocks:
typedef void(^WrappableBlock)(void);
^(WrappableBlock block) {
@try {
block();
}
@catch(...)
}
//handle exception
}
}
However, it's very important to realize that the Cocoa (and CocoaTouch) libraries are not exception-safe. Throwing an exception through Cocoa frameworks will lead to all sorts of problems as the frameworks will not properly handle or clean up from the exceptions, leaving your application in a possibly inconsistent state. The correct Cocoa-style is to use NSError
and return flags to indicate error conditions. This is neither better nor worse than using exceptions, just a different philosophy.
To do something similar to your universal_handling
with NSError
is not quite so straight forward because it will require that anything you call comply with the NSError
pattern. That said:
typedef BOOL(^WrappableBlock)(NSError**);
^(WrappableBlock block, NSError **err) {
BOOL success = block(err);
if(!success) {
// handle error
}
return success;
}
would wrap any method that takes just an NSError**
and returns a BOOL
to indicate the presence of an error. Obviously the utility of this wrapper is limited as you'll have to wrap any interesting method in an other block to handle any other parameters. Of course, since it's the NSError**
pattern, you can always just handle the errors when/where you want and pass NULL
as the NSError**
parameter where you don't care (ignoring the return value).
One final note: if you are using libraries that may throw exceptions, you must catch those exceptions within the scope of the library call and handle them. Do not let the exceptions propagate as they might then propagate through Cocoa framework code. Thus, the utility of the universal_handling
block you propose is limited.
Upvotes: 5
Reputation: 14419
I would suggest you this nice cocoawithlove article that explains how to handle unhandled exceptions in Objective-C and also how to recover from an exception instead of "just" crashing. That could be a good alternative to what you are looking for.
I'm afraid that Objective-C not being as dynamic as ruby, that is a bit harder to do.
Would love to see a good block based implementation too, if that's possible, even If I'm not using them yet, because of previous version compatibility.
Upvotes: 0