Swift中如何避免多层嵌套的do try catch语句?
解决Swift中do-try-catch嵌套问题
针对多模型解码导致do-try-catch嵌套的问题,有几种简洁的方式可以扁平化代码,后续添加新模型也更方便:
方法1:通用解码函数 + if-else链
先封装一个通用的可选型解码函数,利用try?将解码错误转为nil:
private func attemptDecode<T: Decodable>(_ type: T.Type, from data: Data) -> T? { return try? JSONDecoder().decode(type, from: data) }
然后用if-else依次尝试解码不同模型:
if let sendModel = attemptDecode(SendResponseModel.self, from: data) { redirectUserToScreen1(sendModel) } else if let anotherModel = attemptDecode(SendAnotherResponseModel.self, from: data) { redirectUserToScreen2(anotherModel) } // 后续添加新模型只需在这里追加else if分支 else { dprint("所有模型解码失败") }
这种方式完全消除了嵌套,逻辑清晰,新增模型时只需添加新的else if判断即可。
方法2:模型-处理闭包数组(适合大量模型场景)
如果后续要添加的模型很多,可以把"模型类型+对应处理逻辑"封装成数组,通过循环依次尝试:
// 定义元组数组,存储模型类型和对应的成功处理闭包 let decodingTasks: [(modelType: Decodable.Type, handler: (Decodable) -> Void)] = [ (SendResponseModel.self, { model in redirectUserToScreen1(model as! SendResponseModel) }), (SendAnotherResponseModel.self, { model in redirectUserToScreen2(model as! SendAnotherResponseModel) }) ] // 遍历数组尝试解码,成功则执行处理逻辑并跳出循环 for task in decodingTasks { guard let model = try? JSONDecoder().decode(task.modelType, from: data) else { continue } task.handler(model) break } // 可选:判断是否所有解码都失败 let allFailed = decodingTasks.allSatisfy { task in try? JSONDecoder().decode(task.modelType, from: data) == nil } if allFailed { dprint("所有模型解码失败") }
这种方式的优势是新增模型时只需在数组里添加新的元组条目,无需修改判断逻辑,扩展性更强。
补充说明
如果需要单独处理每个模型的解码错误(而非统一捕获),可以把解码函数的返回值改为Result<T, Error>,但上述两种方式已经能解决当前的嵌套问题,且代码更简洁。
内容的提问来源于stack exchange,提问作者fabiobh
相关产品推荐
相关产品推荐

