【SwiftUI】SceneStorageで画面遷移状態の維持

SwiftUI

SceneStorageで画面遷移状態の維持が簡単に出来ます。
Appleのアプリ状態の維持に関するドキュメントとサンプルはこちら。

Restoring Your App’s State with SwiftUI | Apple Developer Documentation
Provide app continuity for users by preserving their current activities.

そのままだと結構色々やってあるので、
今回はNavigationLinkだけ抜き出して最小限の構成で紹介します。

SceneStorageを使う理由

まずSceneStorageでやる理由は、iPadOSのMultiple Windowsに対応する為です。
デフォルトでEnable Multiple WindowsがYESになっているんですよね。

なおSceneStorageはSessionが破棄されるとクリアされます。
バックグラウンドで置いておいてメモリがクリアされる分には復帰できますが、
このSessionの破棄には若干癖があるみたいでAppスイッチャーで閉じると、
破棄される場合と残る場合がありますが、私はよくわかってません。

単一WindowのみのアプリであればAppStorageでも良いです。
こちらだとSessionが破棄されても状態が残るので、状況によって使い分けると良いと思います。

コードと解説

struct ContentView: View {
    
    @SceneStorage("selection") var selection:Int?
    
    var body: some View {
        NavigationView{
            List{
                ForEach(0..<5){ index in
                    NavigationLink(
                        destination: Text("Destination \(index)"),
                        tag: index,
                        selection: self.$selection,
                        label: {Text("Navigate \(index)")})
                }
            }.navigationTitle("NavigationView")
        }
    }
}

最小限にするとコレだけです。AppStorageと同じ感じですね。
アプリ全体で保持するかセッション単位で保持するかの違いです。

ざっくりこんな感じで、左のリストから選択すると右のViewに切り替わります。
この状態でアプリを閉じてもSessionが維持されていれば、
右のViewの状態から表示してくれます。

それでは要点を見て行きましょう。

@SceneStorage("selection") var selection:Int?

@SceneStorageと言うことで@Stateの様にProperty Wrappersなので、
変更が検知されてViewが再描画されます。

(“selection”) ここはSceneStorageに保存するKeyです。
この値が同じであればSession内の同じデータにアクセスします。
複数のView扱う場合にKeyさえ合わせれば、変数名は異なる物でも問題ありません。

var selection:Int? 今回はNavigationLinkと合わせる為にOptionalになっています。
SceneStorageが対応している型であれば問題ありませんし、
他の使い方ならばOptionalの必要もないですし初期値の指定もできます。

@SceneStorage("text") var inputText = "Default Value"

TextFieldの値を保持する場合はこんな感じでしょうか。

初期値を指定した場合は、データがない場合に初期値が入り、
データがある場合は保存されていた値が自動的に読み込まれます。

ForEach(0..<5){ index in

    NavigationLink(
        destination: Text("Destination \(index)"),
        tag: index,
        selection: self.$selection,
        label: {Text("Navigate \(index)")})

}

NavigationLinkはtagとselectionの引数があるものを使います。
selectionの変数にタグの値が入ると自動的に画面が遷移します。
またNavigationLinkがタップされた場合にはselectionにtagの値が自動的に入ります。
そしてdestinationから戻ってくればselectionはnilになります。

そのため、SceneStorageと組み合わせると、
他にSave/Loadや遷移の処理を書かずにViewの遷移状態の維持が行われます。

NavigationView以外にも、このような引数を持ったViewは多いので、
色々なViewで試してみてください。

コメント

  1. […] 【SwiftUI】SceneStorageで画面遷移状態の維持SceneStorageで画面遷移状態の維持が… […]

  2. […] 【SwiftUI】SceneStorageで画面遷移状態の維持SceneStorageで画面遷移状態の維持が… […]

タイトルとURLをコピーしました