1

プロトコルの拡張機能から提供される関数を介してstructsJSON 辞書 ( ) から初期化するいくつかのオブジェクトがあります (「辞書/配列を使用して Codable に準拠するオブジェクトを初期化する」を参照)。[String : Any]initDecodable

基本的に、次のようなオブジェクトがあります。

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ます。

didSetonを使用できます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クロージャー内に作成されinitdidSet.

initまた、 fromDecodableプロトコル (クロージャー内のもの)によって提供される init を「オーバーライド」することはできません。これはtry? ObjectModelB(any: $0)、オブジェクトが でありstruct、これは継承ではなく、プロトコルによって提供されるイニシャライザーにすぎないためです。initそれ以外の場合は、オブジェクトの を「オーバーライド」してsuper.initから、複雑なプロパティを更新するある種の変更関数を実行し、複雑なプロパティを作成しますprivate(set)

私が考えることができる他の唯一のオプションは、先ほど述べた変更関数を作成し、それをdidSetwhenarrayOfObjectModelAVal変更の両方で呼び出してから、オブジェクトの初期化呼び出しを次のように更新することです。

guard let objectDictArray = responseObject as? [[String : Any]] else { return }
let objects = objectDictArray
    .compactMap({ try? ObjectModelB(any: $0) })
    .forEach({ $0.updateProperties() })

しかし、今updatePropertiesでは誰でもいつでも呼び出すことができ (これは本当に負担が大きいため悪いことです)、開発者がその役割を忘れる可能性があるため、オブジェクトの配列を作成するときにも呼び出されるという保証はありませんforEachupdatePropertiesしたがって、オブジェクトの初期化直後に関数を自動的に呼び出す方法が必要な理由。

4

1 に答える 1