[SwiftUI] To get Binding<T> and mutate from ObservedObject

Created
Sep 16, 2019 7:22 AM
Tags
SwiftUI.frameworkMemo
Keywords

@State はなく External Storageを使用する場合に必要になる @ObservedObject の挙動を探る。

class Store: ObservableObject {
  
  let age = 20
  
  var name = "" {
    didSet {
      print("Updated", name)
    }
  }
  
}

ObservedObjectを作ります。

let observedStore = ObservedObject.init(initialValue: Store())

PropertyWrapperを使う場合

@ObservedObject var store: Store = .init()

間接的にnameを購読・更新するためのBindingを取り出せます。

let nameBinder: Binding<String> = observedStore.projectedValue.name

しかし、ageは取り出すことができません。

Can not get age as Binding<Int>, age is constant.

observedStore.projectedValue.age

ObservedObject<T>.Wrapperのsubscriptは次のように実装されている。

public subscript<Subject>(dynamicMember keyPath: ReferenceWritableKeyPath<ObjectType, Subject>) -> Binding<Subject> { get }

ReferenceWritableKeyPathとして取れるプロパティのみ受け付けていることが分かる。

ageをBindingから更新する

let ageBinder: Binding<String> = observedStore.projectedValue.name

ageBinder.wrappedValue = "Hello"

observedStore.wrappedValue.name