💁‍♂️

【SwiftUI】dismiss()はシートやポップオーバーなどの現在の表示を却下する

2023/04/03に公開

はじめに

主張

  • dismiss()は以下のシーンで表示を却下できる
    • .sheet.confirmationDialog, .popoverのようなモーダル
    • NavigationStackにおける現在のView
  • dismiss()はdismissするViewで環境値を設定しなければならない

本題

dismiss().sheet,.confirmationDialog,.popoverのようなモーダル表示を閉じる

ここでは、.sheetを例にdismiss()を使用する。
ParentViewのボタンからシートを呼び出し、ChildViewのボタンでシートを閉じる。

ParentView
import SwiftUI

struct ParentView: View {
    
    @State private var showSheet: Bool = false
    
    var body: some View {
        Button("シートを表示") {
            showSheet.toggle()
        }
        .sheet(isPresented: $showSheet) {
            ChildView()
        }
    }
}
ChildView
import SwiftUI

struct ChildView: View {
    
    @Environment(\.dismiss) private var dismiss
    
    var body: some View {
        Button("閉じる") {
            dismiss()
        }
    }
}

dismiss()を使ってNavigationStack上で現在の表示から前の画面に戻る

ParentView
import SwiftUI

struct ParentView: View {
    
    var body: some View {
        NavigationStack {
            List {
                NavigationLink("ChildViewへ") {
                    ChildView()
                }
            }
            .navigationTitle("ParentView")
        }
    }
}
ChildView
import SwiftUI

struct ChildView: View {
    
    @Environment(\.dismiss) private var dismiss
    
    var body: some View {
        Button("閉じる") {
            dismiss()
        }
        .navigationTitle("ChildView")
    }
}

dismiss()はdismissするViewで環境値を設定しなければならない

以下のコードでは正しくシートを閉じることができません。

import SwiftUI

struct ParentView: View {
    
    @Environment(\.dismiss) private var dismiss
    
    @State private var showSheet: Bool = false
    
    var body: some View {
        Button("シートを表示") {
            showSheet.toggle()
        }
        .sheet(isPresented: $showSheet) {
            ZStack {
                Color.yellow
                Button("閉じる") {
                    dismiss()
                }
            }
        }
    }
}

上記のコードでは、ParentViewに環境値dismissが設定されていることになり、dismissしたいViewではありません。
なので、前のセクションのように、Viewを分けて正しいViewで環境値dismissを設定する必要があります。

まとめ

  • dismiss()は以下のシーンで表示を却下できる
    • .sheet.confirmationDialog, .popoverのようなモーダル
    • NavigationStackにおける現在のView
  • dismiss()はdismissするViewで環境値を設定しなければならない

Discussion