SwiftUI

Dismiss Presented View

Phililip
728x90

안녕하세요.

 

 

 

Cancel을 누르면 modal sheet가 닫히는 이런 화면 많이 보셨죠??

 

기존에는 presentationMode를 사용해서 presented 되어 있는 뷰를 닫았는데, iOS 15부터는 dismiss라는 것을 사용하도록 바뀌었어요.

 

그래서 이번에는 iOS 14 이하와 iOS 15 이상에서 화면에 띄워져 있는 뷰를 dismiss 시키는 방법에 대해 알아볼게요.

 

 


 

## 1. PresentationMode (iOS 14 이하)

뷰를 화면에 출력할 때는 보통 아래처럼 sheet 수식어나 fullScreenCover 수식어를 사용합니다.

struct ContentView: View {
    @State private var isShowingCart = false
    
    var body: some View {
        Button(action: { isShowingCart.toggle() }) {
            Text("Add to cart")
        }
        .sheet(isPresented: $isShowingCart) {    ✅
            CartView()
        }
    }
}

 

 

그리고 아래처럼 Save, Cancel 버튼을 나오게 하려면 ToolbarItem을 사용해야겠죠??

 

 

struct CartView: View {
    var body: some View {
        NavigationView {
            Text("Cart")
                .toolbar {     
                    ToolbarItem(placement: .primaryAction) {    ✅
                        Button("Save") {
                            // dismiss presented view
                        }
                    }
                    
                    ToolbarItem(placement: .cancellationAction) {    ✅
                        Button("Cancel", role: .cancel) {
                            // dismiss presented view
                        }
                    }
                }
                .navigationTitle("Cart")
        }
    }
}

 

저는 Save나 Cancel 버튼을 눌렀을 때 뷰가 닫혔으면 좋겠어요.

 

이럴 때, presentationMode라는 Environment 변수를 사용해야 합니다.

(presentaionMode는 현재 deprecated 되어 있는 상태이니 참고해주세요!)

 

그냥 사용하는 것은 아니고, presentationMode의 wrappedValue의 dismiss method를 호출해줘야 합니다.

struct CartView: View {
    @Environment(\.presentationMode) var presentationMode
    var body: some View {
        NavigationView {
            Text("Cart")
                .toolbar {
                    ToolbarItem(placement: .primaryAction) {
                        Button("Save") {
                            dismiss()    ✅
                        }
                    }
                    
                    ToolbarItem(placement: .cancellationAction) {
                        Button("Cancel", role: .cancel) {
                            dismiss()    ✅
                        }
                    }
                }
                .navigationTitle("Cart")
        }
    }
    
    private func dismiss() {
        presentationMode.wrappedValue.dismiss()    ✅
    }
}

 

 

 

잘 동작하네요ㅎㅎㅎ 

 

 

근데 코드가 약간.... 귀찮고 직관적이지 않죠??

(presentationMode.dismiss도 아니고 presentationMode.wrappedValue.dismiss 라니....)

 

그래서 iOS 15부터는 좀 더 직관적으로 바뀌었습니다.

 

 

 

## 2. DismissAction (iOS 15 이상)

아래처럼 dismiss라는 Environment 변수를 선언하고

@Environment(\.dismiss) private var dismiss

 

wrapped value를 사용할 필요 없이 dismiss method를 바로 호출해주면 됩니다.

 

이렇게요!!

struct CartView: View {
    @Environment(\.dismiss) private var dismiss    ✅
    var body: some View {
        NavigationView {
            Text("Cart")
                .toolbar {
                    ToolbarItem(placement: .primaryAction) {
                        Button("Save") {
                            dismiss()
                        }
                    }
                    
                    ToolbarItem(placement: .cancellationAction) {
                        Button("Cancel", role: .cancel) {
                            dismiss()
                        }
                    }
                }
                .navigationTitle("Cart")
        }
    }
}

 

조금 더 편리해진 것 같지 않나요??ㅎㅎㅎ

 

 

 

 

## 참고

- https://useyourloaf.com/blog/dismissing-swiftui-views/

 

Dismissing SwiftUI Views

SwiftUI has a less clumsy mechanism for dismissing presented views in iOS 15.

useyourloaf.com

 

 


 

이번 글은 여기서 마무리.

 

 

 

반응형

'SwiftUI' 카테고리의 다른 글

복잡한 Navigation Flow 처리 (feat. Combine)  (0) 2022.05.10
MotionScape  (0) 2022.05.06
Custom Adaptive StackView (feat. ViewBuilder)  (0) 2022.04.17
horizontalSizeClass, dynamicTypeSize  (0) 2022.04.17
Gesture  (0) 2022.04.01