【SwiftUI】編集モードの取得に関する不具合

(2021/07/29 更新)

編集モード(editMode)の取得に関する不具合と思われる現象に遭遇したので、対処方法と一緒に記録を残しておきます。

スポンサーリンク

環境

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

【Xcode】12.5RC
【Swift】5.4
【iOS】14.5
【macOS】Big Sur バージョン 11.5
スポンサーリンク

ケース1(正常動作)

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

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

ケース1(正常動作)

スポンサーリンク

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

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

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

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

考察

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

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

スポンサーリンク

対処方法

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

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

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

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

対処方法

スポンサーリンク

疑問点(未解決事項)

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

疑問事項(1)

しかし、次のように子画面のListとEditButton各々に直接enviromentモディファイアで環境変数を定義してやると、意図した動きになります。

疑問事項(2)

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

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

スポンサーリンク

参考リンク

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

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/05/9 更新)Listで生成したデータ一覧の行削除処理について解説します。
スポンサーリンク
SwiftUI
カピ通信