解决Optional<Wrapped>重复RawRepresentable一致性与AppStorage兼容问题
解决Optional RawRepresentable一致性冲突与@AppStorage适配问题
问题背景
项目中存在以下代码:
RawRepresentable扩展
extension RawRepresentable where Self: Codable { // 返回JSON字符串形式的rawValue public var rawValue: String { if let json = try? JSONEncoder().encode(self), let string = String(data: json, encoding: .utf8) { return string } else { return "{}" } } // 从JSON字符串解析实例 public init?(rawValue: String) { if let value = try? JSONDecoder().decode(Self.self, from: Data(rawValue.utf8)) { self = value } else { return nil } } }
Optional协议一致性声明
extension Optional: RawRepresentable where Wrapped: Codable {}
遇到两个矛盾的编译问题:
- iOS应用目标编译正常,但单元测试目标报错:
Redundant conformance of 'Optional<Wrapped>' to protocol 'RawRepresentable' - 移除
Optional的协议一致性声明后,应用目标中@AppStorage(StorageKeys.bag.rawValue) var bag: Bag? = nil编译失败,提示Bag?无法匹配@AppStorage支持的基础类型(Bool/Int/String等)
解决方案
方案1:通过条件编译隔离应用与测试目标的一致性声明
单元测试环境中可能存在Optional<Wrapped>隐式遵循RawRepresentable的情况,因此可以通过自定义编译标记,只在应用目标中添加该一致性声明:
- 打开Xcode,选中项目 -> 选择应用目标 -> Build Settings -> Swift Compiler - Custom Flags -> Other Swift Flags,添加编译标记
-D APP_TARGET - 修改
Optional的一致性代码:
#if APP_TARGET // 仅在应用目标中生效,避免测试环境的冗余一致性冲突 extension Optional: RawRepresentable where Wrapped: Codable {} #endif
方案2:为Optional<Wrapped: Codable>实现专属RawRepresentable逻辑
直接为Optional实现RawRepresentable的具体方法,替代单纯的一致性声明,同时处理nil的特殊情况(原扩展未覆盖Optional.nil的编码逻辑):
extension Optional: RawRepresentable where Wrapped: Codable { public typealias RawValue = String public var rawValue: String { guard let wrappedValue = self else { return "null" } // 复用原有的JSON编码逻辑 if let jsonData = try? JSONEncoder().encode(wrappedValue), let jsonString = String(data: jsonData, encoding: .utf8) { return jsonString } return "{}" } public init?(rawValue: String) { if rawValue == "null" { self = nil return } // 复用原有的JSON解码逻辑 guard let jsonData = rawValue.data(using: .utf8), let wrappedValue = try? JSONDecoder().decode(Wrapped.self, from: jsonData) else { self = nil return } self = wrappedValue } }
此方案无需条件编译,直接覆盖Optional的RawRepresentable实现,同时解决了nil值的编码/解码问题,适配@AppStorage的要求。
内容的提问来源于stack exchange,提问作者Jobie J
相关产品推荐
相关产品推荐

