🔙

SwiftUIのdismissとは?

2024/02/10に公開

Overview

https://developer.apple.com/documentation/swiftui/environmentvalues/dismiss

議論
この環境値を使用して、現在の環境の DismissAction インスタンスを取得します。 次に、インスタンスを呼び出して削除を実行します。 インスタンスを直接呼び出すのは、インスタンスを呼び出すときに Swift が呼び出す callAsFunction() メソッドが定義されているためです。

このアクションを使用して次のことができます。

シートやポップオーバーなどのモーダル プレゼンテーションを閉じます。

NavigationStack から現在のビューをポップします。

WindowGroup または Window で作成したウィンドウを閉じます。

アクションの具体的な動作は、それをどこから呼び出すかによって異なります。 たとえば、シートとして機能するビュー内に DismissAction を呼び出すボタンを作成できます。

private struct SheetContents: View {
    @Environment(\.dismiss) private var dismiss


    var body: some View {
        Button("Done") {
            dismiss()
        }
    }
}

summary

日本語に翻訳すると破棄をするとか書いてあるけど、やることはボタンにページを閉じるロジックを書くだけですね。Flutterで説明するなら、popという前のページに戻す処理がありますね。

TODOアプリを例に出すとこんな感じですね。詳細ページがあってそこから編集ページへ画面遷移して、編集ページでデータを更新すると、popというかdismissして、編集 -> 詳細へ戻ります。

詳細ページ:

import SwiftUI

struct TodoDetailsView: View {
    let detailTodo: Todo
    
    var body: some View {
        VStack(alignment: .leading) {
            HStack {
                Text(detailTodo.title).bold()
                Text(detailTodo.date, style: .date).foregroundStyle(.secondary)
            }
            .padding(.bottom,1)
            HStack {
                Text(detailTodo.note)
                    .lineLimit(1)
                    .foregroundStyle(.secondary)
            }
            .padding(.bottom,1)
            HStack {
                Text(String(repeating:"⭐️", count: Int(detailTodo.importance)))
            }
        }
    }
}

#Preview {
    TodoDetailsView(detailTodo: Todo(title: "Grocery Shopping", note: "Need to buy vegetables and fruits", importance: 3, date: Date()))
}

編集ページ:

import SwiftUI

struct EditTodoView: View {
    @Environment(\.modelContext) private var modelContext
    @Environment(\.dismiss) var dismiss
    
    @State var editingTodo: Todo
    @State var eidtMode = false
    
    var body: some View {
        if eidtMode {
            Form{
                TextField("Title", text: $editingTodo.title)
                DatePicker("Date", selection: $editingTodo.date, displayedComponents: .date)
                Text(String(repeating:"⭐️", count: Int(editingTodo.importance)))
                Slider(value: $editingTodo.importance, in: 1...5, step:1)
                TextEditor(text: $editingTodo.note)
                    .frame(minHeight: 200)
            }
            .navigationTitle("Edit Mode")
            .toolbar{
                Button("Delete") {
                    modelContext.delete(editingTodo)
                    dismiss()
                }
                .foregroundColor(.red)
                Button("Done") {
                    eidtMode = false
                }
            }
        } else {
            TodoDetailsView(detailTodo: editingTodo)
                .toolbar{
                    Button("Edit"){
                        eidtMode = true
                    }
                }
        }
    }
}

#Preview {
    EditTodoView(editingTodo: Todo(title: "sample task", note: "sample nopte", importance: 3, date: Date()))
}

thoughts

短い記事になりましたが、dismissは、単純にモーダルを閉じたり前のページに戻る処理を書くためのコードのようです。

これが、Todoアプリの全体のコードです。参考してみてください。
https://github.com/sakurakotubaki/SwiftUITodoApp

Discussion