1

I have a BaseView something like this and I want to add alert mechanism to all my subviews

struct BaseView<Content: View>: View {
    @State var isAlertPresented = false
    let content: Content
    
    init(@ViewBuilder content: () -> Content) {
        self.content = content()
    }
    
    var body : some View {
        content.alert(isPresented: $isAlertPresented) {
            Alert(title: Text("title"))
        }
    }

}

And here is my SubView.

struct SubView: View {
    BaseView {
        Text("")
    }.onReceive(vm.publisher) { (output) in
        // here I want to trigger BaseView isAlertPresented property        
        // BaseView.isAlertPresented = true
    }
}

Can I do something like this? If yes how can I?

1 Answer 1

1

If view contains BaseView it is definitely not a subview relating to it. And you should not access/manipulate internal state of other view due to single-source-of-truth violation.

Instead you have to use Binding in this scenario, like below (tested with Xcode 11.7)

struct BaseView<Content: View>: View {
    @Binding var isAlertPresented: Bool
    let content: Content

    init(isAlertPresented: Binding<Bool>, @ViewBuilder content: () -> Content) {
        self._isAlertPresented = isAlertPresented
        self.content = content()
    }

    var body : some View {
        content.alert(isPresented: $isAlertPresented) {
            Alert(title: Text("title"))
        }
    }

}

struct SomeOtherView: View {
    @State private var showAlert = false

    var body: some View {
        BaseView(isAlertPresented: $showAlert) {
            Text("Test")
        }
        .onReceive(vm.publisher) { (output) in
//        .onAppear {     // used instead of above just for test
            self.showAlert = true
        }
    }
}
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks Asperi. That solution ok for me. But I have 30 otherViews. Can I have to put @Binding var isAlertPresented: Bool property for all of my views?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.