Swift中优雅标记输入错误的数据结构方案咨询
我正在开发一款工具,它接收包括部分文件在内的特定输入集,对输入进行解析、错误检查,若无错误则执行实际操作。
该工具需验证规范中预定义的约20种带有特定错误信息的输入错误。
作为Swift新手,我原本可以不使用任何数据结构实现这些错误检查,但对枚举的用法很感兴趣,想探索在此场景下使用枚举是否合理。
我计划编写如下代码:
enum ErrorCheck { case incorrectFilePathProvided (code: Int, description: String) case inputFileIsMissingVersionNumber (code: Int, description: String) .... } let errorIncorrectFilePathProvided = ErrorCheck.inputFileNotProvided(1, "User has provided incorrect input file") .... static func validateInputParams(param1: String, param2: NSDictionary) -> NSArray { var result: NSMutableArray = [] if !param1.hasPrefix("/Application") { result.add([ErrorCheck.errorIncorrectInputFilePathProvided.code : ErrorCheck.errorIncorrectInputFilePathProvided.description]) } if !param2["specificKey"] { result.add([ErrorCheck.errorIncorrectInputFilePathProvided.code : ErrorCheck.errorIncorrectInputFilePathProvided.description]) } }
请问该方案是否合理?或者有无更符合Swift风格的实现方式?
用枚举管理这类预定义的输入错误完全合理,甚至是非常合适的选择,但你当前的写法还有不少可以优化的地方,能更贴合Swift的原生风格:
1. 让枚举实现Error协议
Swift原生的Error协议是处理错误的标准范式,让你的枚举遵循它,能更好地兼容Swift的错误处理机制(比如throw、do-catch)。同时可以把错误码、描述做成枚举的计算属性,避免每个case重复携带关联值,让代码更整洁:
enum InputValidationError: Error { case incorrectFilePathProvided case inputFileIsMissingVersionNumber // 补充其他约20种错误case // 计算属性返回对应错误码 var code: Int { switch self { case .incorrectFilePathProvided: return 1 case .inputFileIsMissingVersionNumber: return 2 // 为每个case匹配对应的错误码 } } // 计算属性返回错误描述 var description: String { switch self { case .incorrectFilePathProvided: return "User has provided incorrect input file" case .inputFileIsMissingVersionNumber: return "Input file does not contain a version number" // 为每个case匹配对应的描述 } } }
这种写法的好处是,所有错误的码和描述都集中管理,不会出现关联值拼写错误或不匹配的问题,后续维护也更方便。
2. 替换Objective-C类型为Swift原生集合
你代码里用的NSArray、NSMutableArray、NSDictionary都是Objective-C的类型,Swift有更安全的原生集合类型,比如[InputValidationError]、[String: Any],类型更明确,还能避免隐式转换带来的问题:
static func validateInputParams(param1: String, param2: [String: Any]) -> [InputValidationError] { var errors: [InputValidationError] = [] if !param1.hasPrefix("/Application") { errors.append(.incorrectFilePathProvided) } // 注意这里要匹配正确的错误case,你原代码里写错了 if param2["specificKey"] == nil { errors.append(.inputFileIsMissingVersionNumber) } return errors }
如果需要把错误转换成字典格式对外输出,可以给枚举加个扩展方法:
extension InputValidationError { func toDictionary() -> [String: Any] { return ["code": code, "description": description] } } // 使用示例 let validationErrors = validateInputParams(param1: "testPath", param2: [:]) let errorDicts = validationErrors.map { $0.toDictionary() }
3. 扩展性优势
后续如果需要新增错误类型,只需要在枚举里添加新的case,然后补充code和description的switch分支即可,维护成本极低,这正是枚举处理这类场景的核心优势。
总的来说,你的思路方向完全正确,优化后的写法更符合Swift类型安全、简洁的风格,也能更好地融入Swift的错误处理体系。
内容的提问来源于stack exchange,提问作者agent.smith

