Swift中基于JSON的RawRepresentable枚举通用初始化方案问询
通用RawRepresentable枚举初始化方案
我完全懂你的痛点:手里一堆基于String、Int的枚举,每次从JSON里取可选值初始化都要写重复的判断逻辑,太啰嗦了。下面就给你一套用Swift泛型实现的通用方案,一次扩展搞定所有枚举的初始化需求。
需求回顾
你有这类枚举:
enum TextAlign: String { case left, center, right } enum CornerRadius: Int { case none, medium, large } enum Spacing: String { case tight, medium, loose }
想要实现:从Any?类型的JSON值初始化枚举,失败时自动用默认值,而且不用给每个枚举单独写代码。
最终实现(最符合Swift风格)
直接扩展RawRepresentable协议,添加两个初始化器——一个处理可选值转换的可失败初始化器,一个带默认值的便捷初始化器:
extension RawRepresentable { // 带默认值的便捷初始化:失败时返回默认值 init(from value: Any?, or defaultValue: Self) { self = Self.init(from: value) ?? defaultValue } // 可失败初始化:处理Any?到RawValue的转换和枚举初始化 init?(from value: Any?) { guard let rawValue = value as? Self.RawValue, let instance = Self.init(rawValue: rawValue) else { return nil } self = instance } }
如何使用
现在调用起来超简洁,两种方式任你选:
let json: [String: Any] = [ "textAlign": "left", "cornerRadius": 0, "badSpacing": "invalid" // 不存在的枚举值 ] // 方式1:带默认值,直接返回非可选枚举 let cornerRadius = CornerRadius(from: json["cornerRadius"], or: .medium) // .none let spacing = Spacing(from: json["badSpacing"], or: .medium) // .medium(转换失败用默认) // 方式2:可失败初始化,返回Optional枚举 let align = TextAlign(from: json["textAlign"]) // Optional(.left) let missingAlign = TextAlign(from: json["missingKey"]) // nil
方案亮点
- 全类型兼容:不管你的枚举原始值是String、Int还是其他符合
RawRepresentable要求的类型,都能直接用 - 零重复代码:一次扩展,所有枚举受益,不用再写重复的判断逻辑
- Swift风格拉满:用初始化器替代静态方法,调用方式更符合Swift的语法习惯
参考中间实现(可选)
之前你尝试过的静态方法版本也能工作,比如:
extension RawRepresentable { static func create<T>(_ value: Any?, defaultValue: Self) -> Self where Self.RawValue == T { guard let rawValue = value as? T, let instance = Self.init(rawValue: rawValue) else { return defaultValue } return instance } }
但初始化器的写法更贴合Swift的设计理念,调用起来也更直观。
内容的提问来源于stack exchange,提问作者Gertjan.com
相关产品推荐
相关产品推荐

