Swift调用抛异常的Objective-C函数不识别throws的解决方法
问题根源
既不是Swift调用方式错误,也不是语法层面的低级写法错误,核心是原有Objective-C代码的错误传递逻辑不符合Swift与OC的互操作规则:
- OC中
@throw语法用于抛出NSException类型的运行时异常,这类异常的定位是处理不可恢复的编程错误(如数组越界、非法参数调用等逻辑bug),Swift默认不会桥接这类异常,也不会将抛出NSException的OC函数识别为Swift的throws函数,自然无法用do-catch捕获。 - 原有代码本身不符合OC的异常惯例:
@throw后传入的是NSError实例,而OC生态中NSError的设计定位是传递可恢复的业务错误,和@throw的使用场景完全不匹配。 - 原有OC代码还存在语法瑕疵:
[NSError errorWithDomain: @"FocusError", code: 12]不符合OC方法调用规则,OC方法参数不需要用逗号分隔,该初始化方法需要补全第三个userInfo参数传nil才能正常编译。
适配方案
要让Swift可以正常捕获错误,需要按照Apple官方的OC错误传递规范改写函数,使用NSError**二级指针作为出参传递错误,Swift会自动将符合规范的OC函数桥接为throws类型的Swift函数。
改写后的Objective-C代码如下:
// 函数签名规则:返回BOOL标识操作是否成功,倒数第二个参数为NSError **用于传递错误,业务返回值通过出参返回 BOOL GetFocusModeWithString(NSString *mode, AVCaptureFocusMode *outFocusMode, NSError **error) { if ([mode isEqualToString:@"locked"]) { if (outFocusMode != NULL) { *outFocusMode = AVCaptureFocusModeLocked; } return YES; } else if ([mode isEqualToString:@"auto"]) { if (outFocusMode != NULL) { *outFocusMode = AVCaptureFocusModeAutoFocus; } return YES; } else { if (error != NULL) { *error = [NSError errorWithDomain:@"FocusError" code:12 userInfo:nil]; } return NO; } }
对应的Swift调用代码:
var focusMode: AVCaptureFocusMode = .locked do { try GetFocusModeWithString("auto", &focusMode) // 此处可正常使用解析得到的focusMode } catch { // 此处可正常捕获OC侧抛出的错误 print("聚焦模式解析失败:\(error.localizedDescription)") }
额外说明
注意:如果需要兼容历史遗留的
@throw NSException场景,无法直接在Swift原生层捕获这类异常,需要单独编写OC桥接代码将NSException转换为NSError再桥接到Swift,但这种方案完全不推荐。Apple文档明确说明,NSException抛出后当前调用栈的内存管理状态是不确定的,触发后应该直接终止程序,这类异常仅用于定位编程错误,不适合作为可恢复的业务错误传递载体。
内容的提问来源于stack exchange,提问作者OMGPOP
相关产品推荐
相关产品推荐

