You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Swift 5中编码遵循Encodable的协议数组,是否有更简洁方案?

问题原因

你遇到的错误本质是Swift协议本身不遵循自身——虽然A继承了Encodable,但any A(即擦除类型后的协议实例)并不是一个遵循Encodable的具体类型,JSONEncoder无法为其生成通用的编码逻辑;而[B]是具体类型数组,编译器能自动生成编码代码,因此可以正常运行。

Swift 5 简洁解决方案

以下两种方式都是Swift 5下更直观的处理方案,核心思路是为擦除类型的协议实例提供明确的编码逻辑:

方式一:给协议添加默认编码实现

直接扩展A协议,实现Encodable的要求,通过动态类型获取具体实例的编码逻辑:

protocol A: Encodable {}

extension A {
    func encode(to encoder: Encoder) throws {
        var container = encoder.singleValueContainer()
        try container.encode(self as! Encodable)
    }
}

class B: A {
    var x = 3
}

class C: A {
    var y = 4
}

let items: [A] = [B(), C()]
let encoded = try JSONEncoder().encode(items)
// 输出结果:[{"x":3},{"y":4}]

注:这里的as! Encodable是安全的,因为A本身继承自Encodable,所有遵循类型必然满足Encodable约束。

方式二:使用轻量类型擦除包装器

如果需要更严谨的类型约束,可定义一个包装结构体来承载A实例,明确实现Encodable:

protocol A: Encodable {}

class B: A {
    var x = 3
}

class C: A {
    var y = 4
}

struct AnyA: Encodable {
    private let base: A
    
    init(_ base: A) {
        self.base = base
    }
    
    func encode(to encoder: Encoder) throws {
        try base.encode(to: encoder)
    }
}

let items: [AnyA] = [AnyA(B()), AnyA(C())]
let encoded = try JSONEncoder().encode(items)

这种方式避免了强制类型转换,逻辑更清晰,适合复杂业务场景。

内容的提问来源于stack exchange,提问作者Amos Joshua

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 12:34:57