How to convert an exception into an NSError object

南楼画角 提交于 2020-01-14 04:50:11

问题


I want to convert the message of an exception into an NSError object so that I can use it within a try-catch block (I'm actually working on a native iOS module for React Native).

RCT_EXPORT_METHOD(myMethod:(NSDictionary *)dict
             resolver:(RCTPromiseResolveBlock)resolve
             rejecter:(RCTPromiseRejectBlock)reject)
{
  @try {
    // Do something which could throw something (NS Error or NS Exception)
    resolve(nil);
  } @catch (NSException *exception) {
    // HERE I WANT TO TRANSFORM THE EXCEPTION exception INTO AN ERROR error
    NSError error = ???
    reject(@"my_error", @"Could not do something important", error);
  }
}

I want to convert the exception into an NSError because the third parameter of the reject function (which rejects a Promise on the JS side) expects the input to be of type NSError. I'm not sure whether my solution (using try-catch) is the best thing in this scenario..

In this Apple Developer Guide it says

You can convert an exception into an NSError object and then present the information in the error object to the user in an alert panel.

However the guide does not show a code sample for that and only shows a code sample for a second approach You can also return them indirectly in methods that include an error parameter which seems to complicated for what I want.

So, how would I convert an exception into an NSError? The API reference of NSError does not seem to contain a suitable function..


回答1:


You can't convert NSException to NSError because NSException they do not have the same properties. Is there any reason for catching NSException instead of building a **NSError mechanism? Exceptions are usually fatal and non-recoverable while Errors are non-fatal and recoverable.

If you need to go through with converting an NSException to an NSError anyway, you can do it manually like so:

@try {
    // Something
} @catch (NSException *exception) {
    NSMutableDictionary * info = [NSMutableDictionary dictionary];
    [info setValue:exception.name forKey:@"ExceptionName"];
    [info setValue:exception.reason forKey:@"ExceptionReason"];
    [info setValue:exception.callStackReturnAddresses forKey:@"ExceptionCallStackReturnAddresses"];
    [info setValue:exception.callStackSymbols forKey:@"ExceptionCallStackSymbols"];
    [info setValue:exception.userInfo forKey:@"ExceptionUserInfo"];

    NSError *error = [[NSError alloc] initWithDomain:yourdomain code:errorcode userInfo:info];
    //use error
}



回答2:


NSError is a very flexible class that allows a very extensible error reporting system, thus nobody forbids you to do this:

/// NSExcetion * e = ...;
[NSError errorWithDomain:e.name code:0 userInfo:@{
    NSUnderlyingErrorKey: e,
    NSDebugDescriptionErrorKey: e.userInfo ?: @{ },
    NSLocalizedFailureReasonErrorKey: (e.reason ?: @"???") }];
}

The header files say about NSUnderlyingErrorKey:

The value of this key should be an NSError.

But should is not must and code that blindly relies that something found in a dictionary has a specific class is broken to begin with. Also that's the just the header; the official developer documentation of that key says no such thing and this documentation is authoritative.

And for those who wunder what e.userInfo ?: @{ } and e.reason ?: @"???" means, it's just a shorter way of writing:

e.reason != nil ? e.reason : @"???"

In the end, code may recognize certain errors and handle them in a specific way but all code must be written to accept any error, even unknown ones and offer some kind of default handling for that case. If it is your code, you know that the error domain may be an exception name, so you can check for that and third party code will just treat that as an unknown error.



来源:https://stackoverflow.com/questions/43561531/how-to-convert-an-exception-into-an-nserror-object

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