【问题标题】:How to convert an exception into an NSError object如何将异常转换为 NSError 对象
【发布时间】:2026-02-03 15:00:01
【问题描述】:

我想将异常消息转换为 NSError 对象,以便我可以在 try-catch 块中使用它(我实际上正在处理 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);
  }
}

我想将异常转换为NSError,因为reject 函数的第三个参数(在JS 端拒绝Promise)期望输入为NSError 类型。我不确定我的解决方案(使用 try-catch)在这种情况下是否是最好的。

this Apple Developer Guide 中说

您可以将异常转换为 NSError 对象,然后在警报面板中将错误对象中的信息呈现给用户。

但是该指南没有显示代码示例,只显示了第二种方法的代码示例您也可以在包含错误参数的方法中间接返回它们,这似乎很复杂我要。

那么,如何将异常转换为 NSError? The API reference of NSError 似乎没有包含合适的功能..

【问题讨论】:

  • 您希望如何使用NSError?你真的需要NSError吗?
  • @rmaddy 我编辑了我的代码 sn-p 以更好地反映我的用例,并解释了为什么我想使用 NSError 而不能使用 NSException。或者我可以吗?
  • 这能回答你的问题吗? How can I use NSError in my iPhone App?

标签: ios objective-c exception react-native-ios


【解决方案1】:

您无法将NSException 转换为NSError,因为NSException 它们没有相同的属性。有什么理由抓住NSException 而不是建立**NSError 机制?异常通常是致命且不可恢复的,而错误是非致命且可恢复的。

如果您无论如何都需要将NSException 转换为NSError,您可以像这样手动完成:

@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
}

【讨论】:

  • 捕捉NSException的原因是被抛出的东西。
  • 对不起,来自 Swift 我忘了只有 NSExceptions 可以被 Obj-C 捕获。我已经更新了我的答案。它应该为您提供将异常转换为错误所需的东西。
  • @Oskar 你可以同时捕捉到NSErrorNSException。一个 @catch(id e) 子句或每个子句一个 (@try { ... } @catch(NSError err) { ... } @catch(NSException ex) { ... })
  • @kevin oskar 想说的是,如果一个 NSException * 被抛出,你不能用 NSError * 子句捕捉它
【解决方案2】:

NSError 是一个非常灵活的类,它允许非常可扩展的错误报告系统,因此没有人禁止你这样做:

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

头文件说的是NSUnderlyingErrorKey:

这个键的值应该是一个NSError。

should 不是 must 并且盲目地依赖字典中的某些内容具有特定类的代码一开始就被破坏了。这也只是标题;该密钥的官方开发人员文档没有说这样的事情,并且该文档是权威的。

对于那些想知道e.userInfo ?: @{ }e.reason ?: @"???" 是什么意思的人来说,这只是一种更短的写作方式:

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

最后,代码可能会识别某些错误并以特定方式处理它们,但所有代码都必须编写为接受任何错误,甚至是未知错误,并为这种情况提供某种默认处理。如果是您的代码,您知道错误域可能是异常名称,因此您可以检查它,第三方代码只会将其视为未知错误。

【讨论】:

  • 应该NSDebugDescriptionErrorKey: e.userInfo 而不是NSDebugDescriptionErrorKey: e.description
  • @LeslieGodwin -desrciptionNSObject 的一种方法,仅表示“给我一个描述该对象的可打印字符串”,它几乎可以是任何东西。然而,异常的 userInfo 可以包含大量有用的信息,说明异常发生的方式、原因和位置,但格式是特定于异常的。 NSDebugDescriptionErrorKey 的值在各种调试位置打印为 %@,它调用 -description 的值,并为您提供用户信息异常字典的良好可读打印输出。
  • 我认为将异常名称转换为错误域是一个糟糕的选择——这些是不兼容的,我想说程序员应该为他们的应用程序或库,甚至工作流提供具体的错误域。此外,我会使用来自 NSException 的尽可能多的数据来丰富 userInfo,使用我对异常的了解 - 使用自定义键。