You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 18:48:17