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

Xcode 9.3(Swift 4.1)中Codable类‘has no initializers’问题问询

这个问题我之前升级Xcode 9.3搭配Swift 4.1的时候也踩过坑,其实是Swift编译器自动合成Codable初始化器的机制导致的,咱们来一步步捋清楚原因和解决办法:

问题根源

当两个Codable类放在同一个文件里时,编译器能同时获取到两个类的完整定义。在自动生成Codable相关的初始化逻辑时,它可以确认CodableTwo完全符合Codable要求,并且能被正确初始化,所以不会触发错误。

但把CodableTwo移到单独文件后,编译器处理CodableOne的文件时,只能看到CodableTwo的前向声明——知道它是一个实现了Codable的类,但看不到它的具体属性和自动合成的初始化器细节。这时候编译器没法确定CodableTwo有没有合适的初始化器来完成CodableOne中let another: CodableTwo的初始化,于是就抛出了has no initializers的错误,本质是编译器对自动合成初始化器的“信心不足”了。

解决方案

这里有几个靠谱的解决办法,你可以根据项目情况选择:

1. 手动为CodableOne实现Codable初始化器

既然编译器没法自动合成,那我们手动写一套符合Codable规范的初始化和编码逻辑,明确告诉编译器怎么处理another属性:

class CodableOne: Codable {
    let some: String
    let another: CodableTwo
    
    // 定义CodingKeys,对应属性名
    enum CodingKeys: String, CodingKey {
        case some, another
    }
    
    // 手动实现解码初始化器
    required init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        some = try container.decode(String.self, forKey: .some)
        another = try container.decode(CodableTwo.self, forKey: .another)
    }
    
    // 手动实现编码方法
    func encode(to encoder: Encoder) throws {
        var container = encoder.container(keyedBy: CodingKeys.self)
        try container.encode(some, forKey: .some)
        try container.encode(another, forKey: .another)
    }
}

这样编译器就不用“猜”了,直接用我们写的逻辑,报错自然就消失了。

2. 给CodableTwo添加明确的初始化器

在CodableTwo的文件里,手动添加一个初始化方法(哪怕是对应属性的简单初始化),让编译器能明确知道它有可用的初始化器:

class CodableTwo: Codable {
    var some: String
    
    // 手动添加一个普通初始化器
    init(some: String) {
        self.some = some
    }
    
    // 如果需要保留自动合成的Codable解码逻辑,手动实现这个required初始化器
    required init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        some = try container.decode(String.self, forKey: .some)
    }
}

这样当编译器处理CodableOne时,能看到CodableTwo有明确的初始化器,就会允许自动合成CodableOne的初始化器了。

3. 调整访问级别(应急小技巧,不推荐作为长期方案)

如果两个类在同一个Target下,确保CodableTwo的访问级别是internal(默认就是),或者在CodableOne的文件顶部添加@testable import 你的Target名,有时候能让编译器获取到足够的信息来自动合成初始化器,但这个方法稳定性不如前两个,适合临时应急。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 07:21:46