Swift中如何要求Schema协议实现者遵循Encodable以编码结构体成员
解决方案
强制Schema协议实现者遵循Encodable
直接在定义Schema协议时声明继承Encodable即可实现约束,所有现有遵循Schema的结构体无需修改为类,只要满足Encodable的实现要求就能正常工作:
protocol Schema: Encodable { }
解决协议类型的编码报错
你遇到的Protocol 'X' as a type cannot conform to 'X'是Swift的固有规则:协议作为存在类型使用时,默认不遵循自身,哪怕它继承了Encodable也不能直接作为encode方法的入参。你可以选择以下两种适配方案:
方案1:泛型约束(性能最优,推荐)
如果Foo中存储的Schema是固定单一类型,用泛型让编译器在编译期确定具体类型,完全避开存在类型限制:
// 泛型版本的Foo struct Foo<T: Schema> { let a: T } // 使用示例 struct UserSchema: Schema { let id: Int let name: String } let a = UserSchema(id: 1, name: "张三") let f = Foo(a: a) let jsonData = try JSONEncoder().encode(f.a)
方案2:存在类型/类型擦除(支持异构Schema存储)
如果你需要Foo支持存储任意不同的Schema实现,可以根据你的Swift版本选择对应方案:
- Swift 5.7及以上版本:显式声明存在类型即可直接编码
struct Foo { let a: any Schema } let f = Foo(a: a) let jsonData = try JSONEncoder().encode(f.a)
- Swift 5.7以下版本:使用类型擦除包装器处理编码
// 通用Encodable类型擦除包装器 struct AnyEncodable: Encodable { private let _encode: (Encoder) throws -> Void init<T: Encodable>(_ value: T) { _encode = value.encode(to:) } func encode(to encoder: Encoder) throws { try _encode(encoder) } } // 使用时包装即可 let jsonData = try JSONEncoder().encode(AnyEncodable(f.a))
你之前尝试的
guard let x = f.a as? Encodable写法报错的原因是:Encodable本身是协议,无法作为符合Encodable要求的具体类型使用,因此不能直接传入encode方法作为入参。
内容的提问来源于stack exchange,提问作者Blubber
相关产品推荐
相关产品推荐

