TCA에서 sheet 표시된 View 자체에서 sheet를 닫는 방법

소개



The Composable Architecture (TCA) 로 sheet 표시한 View 를 표시한 측에서 닫는 방법에 대해서, 우선 1 패턴만 나타내 둡니다.

결론


  • SwiftUI의 습관
  • SwiftUI에서는 sheet로 표시한 View를 닫는 방법으로 EnvironmentValues로 PresentationMode
  • PresentationModedismiss() 메서드에서 View를 닫습니다.
  • View에만 한정된 로직으로 View를 닫고 싶을 때는 이것만으로 좋다



  • TCA에서 Reducer의 처리로부터 View를 닫고 싶은 경우 어떻게 할까
  • State 의 변수가 바뀌었을 경우, SwiftUI 의 onChange(of:) 메소드를 검출할 수 있다
  • onChange(of:) 메서드 클로저에서 PresentationMode dismiss() 호출



  • 상세



    SwiftUI에서는 sheet로 표시한 View를 닫는 방법으로 EnvironmentValues로서 PresentationMode가 있다



    샘플 코드로서 ContentView가 ChildView를 sheet에서 열고 ChildView의 PresentationModedismiss() 메소드로 자신을 닫는다.


    )`
    //: A UIKit based Playground for presenting user interface
    
    import UIKit
    import SwiftUI
    import PlaygroundSupport
    
    struct ContentView: View {
    
        @State var isPresented = false
    
        var body: some View {
            NavigationView {
                Button(
                    action: {
                        print("action:", isPresented) // => false
                        isPresented = true
                    },
                    label: {
                        Text("Present View")
                    }
                )
                .sheet(isPresented: $isPresented) {
                    ChildView()
                }
            }
        }
    }
    
    struct ChildView: View {
        @Environment(\.presentationMode) var presentationMode
    
        var body: some View {
            Button(
                action: {
                    presentationMode.wrappedValue.dismiss()
                },
                label: {
                    Image(systemName: "xmark.square")
                    Text("Close")
                }
            )
        }
    }
    
    PlaygroundPage.current.liveView = UIHostingController(rootView: ContentView())
    

    View에만 한정한 로직으로 View를 닫고 싶을 때는 이것만으로 좋다.

    코멘트를 받았기 때문에 주의한 이야기로서, ContentView의 isPresented 는 ChildView를 닫으면 false가 되고 있다.

    이것은 $isPresented$ 를 붙이면 @State 에서 var projectedValue: Binding<Value> { get } 그 때문에 .sheet(isPresented: $isPresented) 에서 seet 에서 false로 할 수 있다.

    TCA에서 Reducer 처리에서 View를 닫으려면 어떻게해야합니까?



    State의 Bool을 준비하고 onChange(of:) 에서 viewStore를 바라보고 그 변화시에 presentationMode를 조작하면 된다.
    struct ChildSttate {
        var isPresented = true
    }
    
    struct ChildView: View {
        @Environment(\.presentationMode) var presentationMode
    
        let store: Store<ChildState, ChildAction>
    
        var body: some View {
            WithViewStore(store) { viewStore in
                Button(
                    action: {
                        presentationMode.wrappedValue.dismiss()
                    },
                    label: {
                        Image(systemName: "xmark.square")
                        Text("Close")
                    }
                )
                .onChange(of: viewStore.isPresented) { value in
                    if !value {
                        presentationMode.dismiss()
                    }
                }
            }
        }
    }
    

    참고

    좋은 웹페이지 즐겨찾기