Copyright © 2022-2024 aizws.net · 网站版本: v1.2.6·内部版本: v1.23.3·
页面加载耗时 0.00 毫秒·物理内存 74.2MB ·虚拟内存 1303.8MB
欢迎来到 AI 中文社区(简称 AI 中文社),这里是学习交流 AI 人工智能技术的中文社区。 为了更好的体验,本站推荐使用 Chrome 浏览器。
项目每积累到一定程度,代码的重构优化是必经之路。
试卷项目初期,整体错误Code较少,直接使用更便于处理错误状态,因此便全部归整到一个单独的 NetWorkError.ResponseCodeType 中,但是随着项目功能的丰富,各个功能模块越来越多,模块错误的处理也各不相同,每个模块都关联了所有的错误Code,后续还会持续增长,导致越来越难以维护。
enum ResponseCodeType: Int { case success = 0 case tokenExpire = 11001 case overVerifyCode = 11011 case verifyCodeExpire = 11002 case verifyCodeIncorrect = 11003 case autoLoginFailed = 11004 case appidLoginFailed = 11005 case phoneIsRegisted = 11006 case phoneHasBinded = 11010 case joinedBeePlan = 11100002 case uploadRepeate = 11020005 case wechatHasBinded = 11010017 case phoneHasBindedOtherWeChat = 11010022 case todayIsSignIned = 11140003 case subjectCountLimit = 11150004 case invalidTagName = 11160002 case alreadyExistsTagName = 11160003 case outOfMaxTagsCount = 11160004 case notRegisterHomework = 11010033 case notSupportNumber = 11010028 case wrongTeamCode = 11210005 case classNotFound = 11210006 case nicknameExists = 11210007 case joinClassThreeTimes = 11210008 case identityNickNameExists = 11210014 case checkClassCodeMax = 11210016 case createClassMAx = 11210015 case joinTeamMax = 11210017 case studentCountMax = 11210018 case other = -99999 }
提前分析、明确目标。
根据期望结果,可以大致选定技术方向
前后对比,不断调优。
struct NetWorkError: Error { var code: ResponseCodeType = .other var msg: String { code.errorString } }
/// 错误类型描述 public protocol ISErrorProtocol { var errorString: String { get } } public enum ModuleRespError<T: ISErrorProtocol>: Error { /// 对应模块自定义类型code case type(_ value: T) /// 基类请求code case baseType(_ value: ResponseCodeType) /// 错误提示归整 public var mapErrorString: String { switch self { case .type(let value): return value.errorString case .baseType(let value): return value.errorString } } }
使用协议的类型占位符 associatedtype,便于后续进行 rawValue 的枚举映射
在ISTargetType协议中关联错误码类型 associatedtype ErrorCodeType: RawRepresentable
public protocol ISTargetType { /// 错误码类型,由各模块自定义 associatedtype ErrorCodeType: RawRepresentable }
/// 根据 ISTargetType 枚举类型调用接口,返回 model static func requestISType<T: ISTargetType>(_ server: T, completion: @escaping (_ model: NetworkModelResponse?, _ code: ResponseCodeType) -> Void) { // ... Network.IS.fetchDataDic(server) { dataDic in guard let dataDic = dataDic, let model: NetWorkResponseModel = NetWorkResponseModel.deserialize(from: dataDic) else { completion(nil, .other) return } // 判断code 是否为token过期 let codeValue = model.ret ?? ResponseCodeType.other.rawValue // errorType let codeType = ResponseCodeType(rawValue: codeValue) ?? .other // 基类Code处理,token过期 NetWorkRequest.checkTokenDidExpire(codeType) // 抛出的code:基类、模块混在一起 completion(model, codeType) } }
/// T.ErrorCodeType: 遵循 RawRepresentable 协议的泛型 /// Result<Success, Failure> 拆分成功、失败逻辑 static func requestISResultType<T: ISTargetType>(_ server: T, result: @escaping ((Result<NetWorkResponseModel, ModuleRespError<T.ErrorCodeType>>) -> Void)) { // ... Network.IS.fetchDataDic(server) { dataDic in // 接口数据处理 guard let dataDic = dataDic, let model: NetWorkResponseModel = NetWorkResponseModel.deserialize(from: dataDic), let retCode = model.ret else { // 接口错误,默认基类错误 let error: ModuleRespError<T.ErrorCodeType> = .baseType(.other) result(.failure(error)) return } if retCode == 0 { // 成功返回 result(.success(model)) return } // 请求失败 if let baseType = ResponseCodeType(rawValue: retCode) { result(.failure(.baseType(baseType))) // 优先处理基类错误code,例如 token失效 NetWorkRequest.checkTokenDidExpire(baseType) } else if let retValue = retCode as? T.ErrorCodeType.RawValue, let moduleType = T.ErrorCodeType(rawValue: retValue) { // 解析并返回模块错误码 result(.failure(.type(moduleType))) } } }
public func queryDemo(with params: [String: String], completionHandler: @escaping (_ model: DemoModel?, _ code: ResponseCodeType) -> Void) { NetWorkRequest.requestISType(GroupQueryServer.createGroup(params)) { model in // ... let code = model.ret ?? -1 let type = ResponseCodeType(rawValue: code) ?? .other guard type == .success, let result = DemoModel.deserialize(from: model.data) else { completionHandler(nil, type) return } completionHandler(.success(resultModel)) } }
logic.queryDemo(with: params) { model, code in // 只能通过解包model来判断接口的成功或失败 guard let model = model else { // 失败处理 handleFail(code: code) return } // 成功处理 hanldeSuccess() } private func handleFail(code: ResponseCodeType) { // ... // 当前模块错误处理 let showWarning = code == .wrongTeamCode || code == .classNotFound // UI处理 warningLabel.isHidden = !showWarning // 提示 CEProgressHUD.showTextHUD(code.errorString) }
public enum StudyGroupRespCode: Int, ISErrorProtocol { case wrongTeamCode = 11210005 case classNotFound = 11210006 case nicknameExists = 11210007 case joinClassThreeTimes = 11210008 case identityNickNameExists = 11210014 case checkClassCodeMax = 11210016 case createClassMAx = 11210015 case joinTeamMax = 11210017 case studentCountMax = 11210018 case folderLevelLimit = 11210027 case curIdentifierError = 11210011 case clockFrequencyInvalid = 11210036 case other }
public func queryDemo(with params: [String: String], completionHandler: @escaping ((Result<ClassItemModel, ModuleRespError<StudyGroupRespCode>>) -> Void)) { // 基类请求 NetWorkRequest.requestISResultType(GroupQueryServer.createGroup(params)) { result in switch result { case .success(let success): // 结果处理que if let resultModel = ClassItemModel.deserialize(from: success.data) { // 转换模块模型model completionHandler(.success(resultModel)) } else { // 转化失败,默认other completionHandler(.failure(.type(.other))) } case .failure(let error): // 抛出的模块错误 completionHandler(.failure(error)) } }
logic.queryDemo(with: params) { result in // 通过 Result 划分结果状态 switch result { case .success(let model): // 成功处理 hanldeSuccess() case .failure(let error): // 失败处理 handleError(error) } } // 示例为简单处理,若需精细化处理错误,拆分优化后的代码,逻辑明显更加清晰 private func handleError(_ error: ModuleRespError<StudyGroupRespCode>) { switch error { case .type(let code): // ... // 当前模块错误处理 let showWarning = code == .wrongTeamCode || code == .classNotFound // UI处理 warningLabel.isHidden = !showWarning // 提示 CEProgressHUD.showTextHUD(code.errorString) case .baseType(let error): // 基类错误处理 CEProgressHUD.showTextHUD(error.errorString) } }
至此,我们已经了解了有关ErrorCode的重构优化的大体逻辑,从后续的开发流程结果可以看出,确实对项目的Code混乱增长有了良好的控制,各模块只需要关注处理自己的异常code,降低了维护代码难度,后续也会持续关注和优化。
参考资料
以上就是Swift Error重构优化详解的详细内容,更多关于Swift Error重构优化的资料请关注编程教程其它相关文章!
背景知识Cocoa API 中有很多接受回调的异步方法,比如URLSession的dataTask(with:comp ...