【SwiftUI】編集モードの取得に関する問題

(2022/02/06 更新)

NavigationViewでの編集モード(editMode)取得に関する問題についてまとめました。

スポンサーリンク

環境

この記事の情報は次のバージョンで動作確認しています。

【Xcode】13.2.1
【Swift】5.5.2
【iOS】15.2
【macOS】Monterey バージョン 12.2
スポンサーリンク

ケース1(正常動作)

Editボタンの操作でViewの編集モードを切り替えるサンプルです。

Text、List共に編集モードの切り替えによって表示が変わります。
これは想定通りの動きです。

UntitledImage

スポンサーリンク

ケース2(うまく動かない)

先程と同じ機能をNavigationViewを使って再現します。
Editボタンはナビゲーションバーに配置しました。

こちらは、Editボタンを押すと、Listは表示が切り替わりますが、なぜかTextの方は変化しません。

UntitledImage

考察

どうやら環境変数の編集モード "@Environment(\.editMode)" はアプリ全体で共有されているわけではなく、画面単位で別々に保持されているようです。
NavigationViewは囲んだViewを別の画面として切り替えるしくみですので、NavigationViewで囲まれたViewとContentViewは内部的には別の画面になり、編集モードも各々個別に保持されます。

EditボタンとListは、NavigationView内の子画面が保持する同一の編集モードを参照するので、連動して動作しますが、Textは親画面であるContentViewの編集モード(envEditMode)を参照している為、連動しないのが理由と考えられます。

対処方法

親画面と子画面で環境変数が共有されていないので、共有可能な環境変数を代わりに提供します。

ポイントは以下の3点です。

①独自の editMode 状態変数を @State 変数として定義します。
②Textは上で定義した編集モードを参照して表示を変えるようにします。
③定義した @State 変数を、environmentモディファイアを使って子画面の環境変数(.editMode)に設定します。

これで期待通り表示が切り替わるようになります。

対処方法

疑問点(未解決事項)

「共有可能な環境変数を代わりに用意するのではなく、親画面の編集モードをそのまま子画面に設定すれば良いのでは?」と考え、次のようなコードを書いてみましたが、うまくいきませんでした。

疑問事項(1)

しかし、次のようにenviromentモディファイアの記述場所を変更してやると、意図した動きになります。

疑問事項(2)

なぜ、このような動きの違いがおきるのか説明つかない為、実践では使いにくいなと思っています。

理由がわかる方、情報いただけるとうれしいです。

スポンサーリンク

ケース3(うまく動かない)

次のケースは、ちょっと不可解な動きで、編集モードへのアクセスが、全く関係なさそうな部分に影響を及ぼす例です。

NavigationLinkで遷移した画面で、一度でもアラートを表示すると、ボトムバー上のボタンが使えなくなります。

①「NextView」で画面遷移
②「Tap me!」をタップすると、デバグ画面に"Tapped!"が表示される
③「Alert」をタップして、アラートを表示させてから閉じる。
④以降は「Tap me!」をタップしても反応しない。

UntitledImage

対処方法

ケース2と同様にNavigationView内側のViewに対して独自の状態変数(editMode)を定義すると、正常に動作します。
正直、全く関連性がわかりませんが、NavigationViewの内側でeditModeを使う時は必ず宣言しておくくらいでも良いのかもしれません

スポンサーリンク

参考リンク

本エントリーを執筆するにあたり、参考にさせてもらった外部サイトです。

SwiftUI and the Intermittent EditMode
Fixing another common environment issue in SwiftUI.
スポンサーリンク

あわせて読みたい記事

【SwiftUI】Viewの編集モード(editMode)について
(2020/11/03 更新) Viewの編集モードについて解説します。
【SwiftUI】Viewの分割
(2020/03/10 更新) 複雑なViewを小さなViewに分割する事で、繰り返しを避け、ソースを見やすくする方法を紹介します。 Viewを分割してもパフォーマンスに大きな影響を及ぼさないのがSwiftUIの特徴の一つです。
【SwiftUI】Listの行削除
(2021/09/26 更新) Listで生成したデータ一覧の行削除処理について解説します。