内容
@State
のpropertyの変更を検知するときは、didSetを使ってはいけない。onChange(of:perform:)を使え。という話です。
きっかけ
swift-developers-japanで
@State
にdidSetを書いちゃダメという記事を見たが自分で実際に書いたらdidSetが呼ばれた。本当にダメなのか?
という趣旨の質問があり、あまり理解できていなかったので調べた。
なぜ@State
でdidSetを使ってはいけないか
@State
のdidSetは呼ばれないことがある。
いつ呼ばれていつ呼ばれないかというと、
@State var num: Int
@Binding var binding: Int
_binding = $num
で定義されているとして
num = 10 // didSet呼ばれる
_num.wrappedValue = 15 // 呼ばれない
binding = 2 // 呼ばれない
という感じになります。
これは@StateのwrapperValueがnonmutatingでwrappedValueを更新しても@State
の値自体は変更されないためのようです。
mutaitngのsetterを持つproperty wrapperを自作してwrappedValueの値を直接更新したら、同様にdidSetは呼ばれませんでした。
これは、property wrapperを使っているからで、wrappedValueの値を変更してもそのproperty wrapperを適用しているproperty自体は変更されないためのようです。
ではどうする?
onChange(of:perform:)を使う。
試してないですが、iOS13では.onReceive(Just(selection))で同様のことができるみたいですlink