Swift Codable对象使用didSet/willSet不触发问题咨询
核心问题解释
Swift 语言的底层规则决定了:实例完成初始化流程之前,所有对存储属性的赋值操作,都不会触发didSet/willSet这类属性观察器。这个行为和是否使用Codable协议没有直接绑定关系。
你遇到的didSet不触发的原因可以拆成两部分说明:
- 首先你代码里的观察器关键字存在拼写错误:Swift 中对应的属性观察器是全小写的
didSet,大写写法DidSet不符合语法规范,本身就无法正常完成观察逻辑绑定。 - 就算修正拼写,系统自动为
Codable协议合成的解码实现,全程都在类的初始化生命周期内完成所有属性的赋值——这个阶段实例本身还没有走完整个初始化流程,哪怕给带观察器的属性赋值,观察逻辑也不会被执行。
补充边界常识:哪怕是你自己手写的普通类初始化方法,在方法内部给带
didSet的存储属性赋值,同样不会触发观察器。只有当实例完全初始化完成后,不管是内部还是外部代码对属性发起的赋值操作,才会正常触发对应的观察逻辑。
常用解决方案
- 自定义实现
init(from:)解码方法,调整赋值顺序触发观察器
按照逻辑改写解码流程:先为所有存储属性完成基础解码赋值,等整个实例的初始化流程走完,再对带观察器的属性做二次赋值,这个二次赋值的动作就会正常触发didSet。参考实现:required public init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) // 基础属性赋值(此阶段处于初始化流程中,赋值不会触发观察器) name = try container.decode(String.self, forKey: .name) lastname = try container.decodeIfPresent(String.self, forKey: .lastname) let decodedAge = try container.decodeIfPresent(Int.self, forKey: .age) // 完成所有基础属性赋值后,对age的赋值将正常触发didSet age = decodedAge } - 抽离观察逻辑为独立方法,在解码完成后显式调用
把原本计划写在didSet里的业务逻辑封装成独立函数,在JSONDecoder完成解码、拿到实例后,直接调用该函数传入初始的属性值执行对应逻辑,不依赖属性观察器的自动触发。 - 注意使用场景差异:如果是实例创建完成之后,外部代码直接修改属性(比如
objTest.age = 25),这种场景下的didSet是可以正常触发的,不会存在兼容问题。
内容的提问来源于stack exchange,提问作者paul590
相关产品推荐
相关产品推荐

