Open1

SwiftUI: モデルをアップデートしてるのにビューが更新されない

kabeyakabeya

モデルをアップデートしているのにビューが更新されない、というのでハマって結構時間を食ったのでメモしておきます。

現象としては、以下のようになります。

  • ビュー側で@ObservedObjectで監視しているモデルデータがある
  • モデルデータは当然@ObservableObjectclassで、監視したい値は@Publishedになっている
  • モデル側で値を変えて、変えたタイミングでその値をprintする
  • ビュー側ではvar bodyの先頭でlet _ = printで、再描画される値をprintする
  • 値を変える→ビューの再描画は、実際にこの順で実行されている。printの順がそうなっている
  • 値を変えたときにprintされる値と、ビューの再描画でprintされる値が違う。ビューの再描画では変更前の値がprintされる

最初は、バックグラウンドから@Publishedの値を変えていて、紫の警告が出たんでそれが原因かなと思っていたんですが、それを直しても更新されない。

で、何か違うものを見ているんじゃないだろうかということで、classにUUIDを追加して同時にprintするようにしたら、変更したときのUUIDと、再描画されるUUIDが違うんですね。

何のことはない、最上位のビューで@EnvironmentObjectに定義して、さらに内側のビューで@StateObjectを定義してってやってしまっていました。そのせいで、別々のオブジェクトを更新・参照していた、という話でした。

App本体に実装する前に軽いプロトを作って動作確認した上で取り込もう、と思ってたんですが、とんだ落とし穴でした。