【发布时间】:2018-11-23 14:26:55
【问题描述】:
我有一些对象,它们是 structs,我通过 init 函数从 JSON 字典 ([String : Any]) 初始化,该函数由 Decodable 协议上的扩展提供(参见 Init an object conforming to Codable with a dictionary/array)。
所以基本上,我的对象看起来像这样:
struct ObjectModelA: Codable {
var stringVal: String
var intVal: Int
var boolVal: Bool
// Coding keys omitted for brevity
}
struct ObjectModelB: Codable {
var doubleVal: Double
var arrayOfObjectModelAVal: [ObjectModelA]
// Coding keys omitted for brevity
var complicatedComputedVar: String {
// expensive operations using the values in arrayOfObjectModelAVal
}
}
ObjectModelB 包含一个ObjectModelA 数组,它还有一个属性,我只想在arrayOfObjectModelAVal 更改时才设置它。
我可以在arrayOfObjectModelAVal 上使用didSet,但这只会捕获未来对arrayOfObjectModelAVal 属性的更改。问题是我正在使用 Web 服务来检索 JSON 数据以创建 ObjectModelB ([[String : Any]]) 的数组,并且我是这样构建它的:
guard let objectDictArray = responseObject as? [[String : Any]] else { return }
let objects = objectDictArray.compactMap({ try? ObjectModelB(any: $0) })
我的对象在 compactMap 闭包内创建,init 不会触发 didSet。
我也不能从Decodable 协议(闭包中的那个:try? ObjectModelB(any: $0))“覆盖”由init 提供的初始化,因为我的对象是struct,这不是继承,它只是一个协议提供的初始化器。否则,我会在我的对象中“覆盖”init,然后只执行super.init,然后执行某种变异函数来更新我的复杂属性,然后将我的复杂属性设为private(set)。
我能想到的唯一其他选择是创建我刚才提到的变异函数,并在 arrayOfObjectModelAVal 更改时在 didSet 中调用它,然后使用以下内容更新我的对象初始化调用:
guard let objectDictArray = responseObject as? [[String : Any]] else { return }
let objects = objectDictArray
.compactMap({ try? ObjectModelB(any: $0) })
.forEach({ $0.updateProperties() })
但是现在updateProperties 可以随时被任何人调用(这很糟糕,因为它真的很费力),并且无法保证在创建对象数组时它甚至会被调用,因为开发人员可能会忘记执行 @ 987654349@ 部分。因此,为什么我想要一种在对象初始化后立即自动调用 updateProperties 函数的方法。
【问题讨论】:
标签: swift swift4 swift-protocols decodable swift-structs