SwiftUI/Basic Property Wrappers

SwiftUI) Binding, presentationMode (Two ways to dismiss view)

iosswift 2021. 9. 13. 14:10

어떤 프로젝트를 보다가, 

다음과 같은 코드를 보고 열심히 찾아보았다.

@Environment(\.presentationMode) var presentationMode

 

결론부터 말하면, SwiftUI 에서 sheet 를 이용할 때 dismiss 하는 방법 중 하나로 많이 쓰이는 방법이고,

보통 두가지 방법이 쓰인다. ( presentationMode, Binding )


1. presentationMode 이용하기.

해당 sheet 에서 'presentation mode environment key' 를 이용하여 스스로를 dismiss 하라고 시키는 방법이다.

 

 

어떠한 view 에서도 presentation mode 를 @Environment(\.presentationMode) 를 이용해 읽을 수 있고, 

wrappedValue.dismiss() 를 call 함으로 dismiss 시킬 수 있다.

 @Environment(\.presentationMode) var presentationMode
presentationMode.wrappedValue.dismiss()

 

 

아래는 예제 코드이다. 

struct ContentView: View {
    @State private var showingDetail = false

    var body: some View {
        Button("Show Detail") {
            showingDetail = true
        }
        .sheet(isPresented: $showingDetail) {
            DetailView1()
        }
    }
}

struct DetailView1: View {
    @Environment(\.presentationMode) var presentationMode

    var body: some View {
        Button("Dismiss Me") {
            presentationMode.wrappedValue.dismiss()
        }
    }
}

ContentView 에서 버튼을 누를 때 showingDetail 를 true 값으로 바꾸고,

그에 따라 DetailView1() 를 sheet 로 present 한다.

 

DetailView1 에서는 "Dismiss Me" 라고 써있는 버튼을 누르면

presentationMode.wrappedValue.dismiss() 가 호출되며, 

이에 따라 해당 뷰가 dismiss (사라지게) 된다. 

(꼭 variable name을 presentationMode 라고 할 필요는 없으나, 관례인듯 하다.)

@State private var showingDetail = false 
다른 view 를 present 할 때 많이 쓰이는 방식이다. 

 

 

 


 

 

2. Binding 이용하기

DetailView2 에 binding 을 넘기는 방식으로, DetailView2 에서 해당 값을 false 로 바꿔줄 때 

그 뷰를 dismiss 시킨다. 

 

이 경우 presenting view (ContentView) 에 @State variable (showingDetail) 을 선언해주어야한다. 

struct ContentView: View {
    @State private var showingDetail = false

    var body: some View {
        Button("Show Detail") {
            showingDetail = true
        }
        .sheet(isPresented: $showingDetail) {
            DetailView2(isPresented: $showingDetail)
        }
    }
}

struct DetailView2: View {
    @Binding var isPresented: Bool

    var body: some View {
        Button("Dismiss Me") {
            isPresented = false
        }
    }
}

 

 

1.ContentView 에서 버튼을 누르면  binding 시킬 variable (showingDetail) 을  DetailView2 로 pass ! -->> DetailView2 는 isPresented 값으로 받음.  (두 변수가 서로 연결, 즉 항상 같은 값을 갖게 됨)

 

2. DissmissingView2 에서 해당 binding 된 값 (@State isPresented) 을 false 로 변환시킬 수 있음 . (변환시 dismiss!) 

두 Views, 즉 DetailView2 와 ContentView 에서 같은 boolean value 를 가리키므로 (showDetail === isPresented) 어느 View 에서나 해당 값을 바꾸면 다른 view 에서도 바로 적용됨. 

 

3. 따라서 DetailView2 에서 버튼 클릭 -> isPresented = false 로 toggle, showingDetail 도 false 로 toggle, ContentView 에서 sheet 가 present 되는 조건은 showingDetail 이 true 일 때 이므로, 해당 조건을 만족시키지 않아 DetailView2 를 dismiss 시킴. 

 

 

(참고로, showingDetail 을 true 로 처음에 선언하게 되면 ContentView 가 출현함과 동시에 sheet (DetailView2) 가 나타난다.)

 

 

 

해당 source 를 참조하였습니다.

https://www.hackingwithswift.com/quick-start/swiftui/how-to-make-a-view-dismiss-itself