プロトコルの拡張機能から提供される関数を介してstructs
JSON 辞書 ( ) から初期化するいくつかのオブジェクトがあります (「辞書/配列を使用して Codable に準拠するオブジェクトを初期化する」を参照)。[String : Any]
init
Decodable
基本的に、次のようなオブジェクトがあります。
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
ます。
didSet
onを使用できますarrayOfObjectModelAVal
が、それはプロパティへの将来の変更のみをキャッチし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
.
init
また、 fromDecodable
プロトコル (クロージャー内のもの)によって提供される init を「オーバーライド」することはできません。これはtry? ObjectModelB(any: $0)
、オブジェクトが でありstruct
、これは継承ではなく、プロトコルによって提供されるイニシャライザーにすぎないためです。init
それ以外の場合は、オブジェクトの を「オーバーライド」してsuper.init
から、複雑なプロパティを更新するある種の変更関数を実行し、複雑なプロパティを作成しますprivate(set)
。
私が考えることができる他の唯一のオプションは、先ほど述べた変更関数を作成し、それをdidSet
whenarrayOfObjectModelAVal
変更の両方で呼び出してから、オブジェクトの初期化呼び出しを次のように更新することです。
guard let objectDictArray = responseObject as? [[String : Any]] else { return }
let objects = objectDictArray
.compactMap({ try? ObjectModelB(any: $0) })
.forEach({ $0.updateProperties() })
しかし、今updateProperties
では誰でもいつでも呼び出すことができ (これは本当に負担が大きいため悪いことです)、開発者がその役割を忘れる可能性があるため、オブジェクトの配列を作成するときにも呼び出されるという保証はありませんforEach
。updateProperties
したがって、オブジェクトの初期化直後に関数を自動的に呼び出す方法が必要な理由。