Swift异步/抛出错误处理问题:自定义错误无法正确捕获
解决Swift自定义错误无法正确捕获的问题
1. 先检查自定义错误枚举的定义与转换逻辑
确保你的EnemyAPIError枚举覆盖了目标错误场景,并且能正确关联系统错误。示例写法:
enum EnemyAPIError: Error, LocalizedError { case invalidURL case networkIssue(Error) case dataDecodingFailed var errorDescription: String? { switch self { case .invalidURL: return "无效的请求链接" case .networkIssue(let error): return error.localizedDescription case .dataDecodingFailed: return "数据解析失败" } } }
2. 在DataService的getEnemy函数中正确抛出自定义错误
你遇到的核心问题大概率是:系统错误直接向上抛出,没有被转换为自定义错误。比如创建URL失败时,要立刻抛出invalidURL,而不是继续执行请求触发系统的“找不到主机”错误。正确写法参考:
class DataService { func getEnemy() async throws -> Enemy { // 先判断URL有效性,直接抛出自定义错误 guard let url = URL(string: "你的请求地址") else { throw EnemyAPIError.invalidURL } do { let (data, response) = try await URLSession.shared.data(from: url) // 额外检查响应状态码,非200也可以转为自定义错误 guard let httpResp = response as? HTTPURLResponse, httpResp.statusCode == 200 else { throw EnemyAPIError.networkIssue(NSError(domain: "API", code: -1, userInfo: [NSLocalizedDescriptionKey: "请求状态异常"])) } let enemy = try JSONDecoder().decode(Enemy.self, from: data) return enemy } catch { // 捕获系统错误,按类型转换为自定义错误 if let urlError = error as? URLError { // 把找不到主机这类URL相关错误,映射到自定义的invalidURL if urlError.code == .cannotFindHost || urlError.code == .badURL { throw EnemyAPIError.invalidURL } else { throw EnemyAPIError.networkIssue(urlError) } } else if error is DecodingError { throw EnemyAPIError.dataDecodingFailed } else { throw EnemyAPIError.networkIssue(error) } } } }
3. ViewModel中错误捕获的顺序要正确
必须先捕获自定义的EnemyAPIError,再用通用catch处理未知错误,否则通用分支会先拦截所有错误。示例:
class EnemyViewModel: ObservableObject { @Published var enemy: Enemy? @Published var errorMsg: String? func fetchEnemyAsync() async { do { let enemy = try await DataService().getEnemy() DispatchQueue.main.async { self.enemy = enemy self.errorMsg = nil } } catch let apiError as EnemyAPIError { DispatchQueue.main.async { self.errorMsg = apiError.localizedDescription // 针对不同自定义错误做针对性处理 switch apiError { case .invalidURL: print("DEBUG: 触发无效URL错误") case .networkIssue(let err): print("DEBUG: 网络错误: \(err.localizedDescription)") case .dataDecodingFailed: print("DEBUG: 数据解析失败") } } } catch { // 这里才处理真正的未知错误 DispatchQueue.main.async { self.errorMsg = "未知错误" print("DEBUG: Unknown error occurred: \(error.localizedDescription)") } } } }
快速排查清单
- 确认
getEnemy中创建URL失败时,是否立刻抛出了invalidURL,而不是继续执行请求 - 检查系统错误捕获分支,是否把
URLError的对应code(比如找不到主机)映射到了自定义错误 - 确保ViewModel中先捕获
EnemyAPIError,再处理通用错误
内容的提问来源于stack exchange,提问作者Vladyslav
相关产品推荐
相关产品推荐

