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

如何在Objective-C中实现类似Swift的枚举式错误处理?

在Objective-C中实现类似Swift枚举式的错误处理

嘿,刚从Swift切换到Objective-C,找不到像Swift枚举那样优雅处理错误的方式?太懂这种落差了!Swift的Error枚举确实把错误场景归类得清清楚楚,Objective-C里虽然没有完全一致的语法,但我们可以用它的特性实现类似的效果,下面给你几种实用的方案:

1. 用NS_ENUM定义错误码+NSError传递错误信息

这是Objective-C里最常用的错误处理方式,相当于把Swift枚举的case映射成错误码,再通过NSError **指针把错误对象传递出来,还能像Swift的LocalizedError那样添加本地化描述。

先定义你的错误枚举(用NS_ENUM):

typedef NS_ENUM(NSInteger, MyAppErrorCode) {
    MyAppErrorCodeInvalidURL,
    MyAppErrorCodeJSONStringConversionFailed,
    MyAppErrorCodeJSONStringifyFailed,
    MyAppErrorCodeHashArrayCastFailed
};

然后封装一个创建自定义NSError的工具方法,类似Swift枚举的localizedDescription:

@interface NSError (MyAppErrors)
+ (instancetype)myAppErrorWithCode:(MyAppErrorCode)code userInfo:(NSDictionary *)userInfo;
@end

@implementation NSError (MyAppErrors)
+ (instancetype)myAppErrorWithCode:(MyAppErrorCode)code userInfo:(NSDictionary *)userInfo {
    NSString *domain = @"com.yourcompany.yourapp.error";
    NSString *localizedDescription;
    switch (code) {
        case MyAppErrorCodeInvalidURL:
            localizedDescription = [NSString stringWithFormat:@"无效的URL:%@", userInfo[@"URLString"]];
            break;
        case MyAppErrorCodeJSONStringConversionFailed:
            localizedDescription = [NSString stringWithFormat:@"JSON字符串转换失败:%@", userInfo[@"FailedString"]];
            break;
        case MyAppErrorCodeJSONStringifyFailed:
            localizedDescription = @"JSON序列化失败";
            break;
        case MyAppErrorCodeHashArrayCastFailed:
            localizedDescription = [NSString stringWithFormat:@"无法将对象转换为哈希数组:%@", userInfo[@"InvalidObject"]];
            break;
        default:
            localizedDescription = @"未知错误";
            break;
    }
    
    NSMutableDictionary *info = [NSMutableDictionary dictionaryWithDictionary:userInfo];
    info[NSLocalizedDescriptionKey] = localizedDescription;
    return [NSError errorWithDomain:domain code:code userInfo:info];
}
@end

然后在方法里使用它,通过指针传递错误:

- (BOOL)convertToJSONString:(id)object error:(NSError **)error {
    if (!object) {
        if (error) {
            *error = [NSError myAppErrorWithCode:MyAppErrorCodeJSONStringifyFailed userInfo:@{@"InvalidObject": object ?: @"nil"}];
        }
        return NO;
    }
    
    // 尝试序列化逻辑...
    NSError *serializationError;
    NSData *jsonData = [NSJSONSerialization dataWithJSONObject:object options:0 error:&serializationError];
    if (!jsonData) {
        if (error) {
            *error = [NSError myAppErrorWithCode:MyAppErrorCodeJSONStringifyFailed userInfo:@{@"OriginalError": serializationError}];
        }
        return NO;
    }
    
    return YES;
}

调用的时候就像这样:

NSError *error;
BOOL success = [self convertToJSONString:someObject error:&error];
if (!success) {
    NSLog(@"错误:%@", error.localizedDescription);
    // 根据错误码做不同处理
    if (error.code == MyAppErrorCodeInvalidURL) {
        // 处理无效URL的情况
    }
}

2. 结合Block回调传递错误

如果你的方法是异步的,用Block回调传递错误会更自然,这也和Swift的Result类型有点像(OC里可以自定义类似Result的Block结构):

先定义一个包含结果和错误的Block类型:

typedef void(^MyAppCompletionBlock)(id _Nullable result, NSError * _Nullable error);

然后在异步方法里使用:

- (void)fetchDataFromURLString:(NSString *)urlString completion:(MyAppCompletionBlock)completion {
    NSURL *url = [NSURL URLWithString:urlString];
    if (!url) {
        NSError *error = [NSError myAppErrorWithCode:MyAppErrorCodeInvalidURL userInfo:@{@"URLString": urlString}];
        completion(nil, error);
        return;
    }
    
    // 发起网络请求...
    NSURLSessionDataTask *task = [[NSURLSession sharedSession] dataTaskWithURL:url completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
        if (error) {
            completion(nil, error);
            return;
        }
        
        // 解析数据...
        id parsedData = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error];
        if (!parsedData) {
            NSError *conversionError = [NSError myAppErrorWithCode:MyAppErrorCodeJSONStringConversionFailed userInfo:@{@"OriginalError": error}];
            completion(nil, conversionError);
            return;
        }
        
        completion(parsedData, nil);
    }];
    [task resume];
}

调用的时候:

[self fetchDataFromURLString:@"invalid-url" completion:^(id  _Nullable result, NSError * _Nullable error) {
    if (error) {
        NSLog(@"请求失败:%@", error.localizedDescription);
        if (error.code == MyAppErrorCodeInvalidURL) {
            // 提示用户输入正确的URL
        }
    } else {
        // 处理返回的数据
    }
}];

3. 额外提示:Objective-C的异常不是用来处理业务错误的

别想着用@try/@catch来处理业务错误哦!OC里的异常一般是用来处理致命错误(比如数组越界、未识别的选择器),而不是像Swift那样处理业务逻辑里的错误场景,苹果官方也不推荐用异常来处理预期内的错误,所以还是老老实实用NSError的方式更规范。

这样下来,虽然语法上不如Swift枚举简洁,但也能实现类似的错误分类、信息传递和本地化描述的效果,完全能覆盖你之前用Swift枚举处理错误的场景啦!

内容的提问来源于stack exchange,提问作者Pavel Bogart

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 04:16:03