Oxford212
Oxford212

Reputation: 129

SwiftUI @Binding didn't update display alert

I trying to display an alert after dismiss the sheet. But when I update the @Binding in the sheet, the alert in home page didn't appear. I don't know what's the problem now. Anyone can explain to me? Is it the problem of using @Binding? If the method/logic of doing this is wrong, what method should I use?

struct ContentView: View {
    @State private var showSheet = false
    @State var showAlert = false

    var body: some View {
        VStack {
            Text("sheet")
                .onTapGesture(perform: {
                    self.showSheet.toggle()
                })
        }
        .sheet(isPresented: $showSheet) {
            AddView(showAlert: self.$showAlert, showSheet: self.$showSheet)
        }
        .alert(isPresented: $showAlert){
            Alert(title: Text("Important message"), message: Text("Wear sunscreen"), dismissButton: .default(Text("Got it!")))
        }
    }

}
struct AddView: View {
    @Binding var showAlert: Bool
    @Binding var showSheet: Bool

    var body: some View {
        Button("Dismiss") {
            self.showSheet = false
            self.showAlert = true
        }
    }
}

Upvotes: 3

Views: 1065

Answers (2)

nicksarno
nicksarno

Reputation: 4235

The real problem is that you are trying to dismiss the sheet and show the alert at the same time. In your code, if you add a 0.5 second delay to the alert, it will work:

struct AddView: View {
        @Binding var showAlert: Bool
        @Binding var showSheet: Bool

        var body: some View {
            Button("Dismiss") {
                self.showSheet = false
                DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
                    self.showAlert = true
                }
            }
        }
    }

However, it's much cleaner to write it like this:

struct ContentView: View {

    @State private var showSheet = false
    @State var showAlert = false

    var body: some View {
        VStack {
            Button(action: {
                self.showSheet.toggle()
            }, label: {
                Text("sheet")
            })
            .accentColor(.primary)
        }
        .sheet(isPresented: $showSheet, onDismiss: showAlertFunction, content: {
            AddView()
        })
        .alert(isPresented: $showAlert){
            Alert(title: Text("Important message"), message: Text("Wear sunscreen"), dismissButton: .default(Text("Got it!")))
        }
    }
    
    func showAlertFunction() {
        showAlert.toggle()
    }

}

struct AddView: View {

    @Environment(\.presentationMode) var presentationMode
    
    var body: some View {
        Button("Dismiss") {
            self.presentationMode.wrappedValue.dismiss()
        }
    }
}

Upvotes: 2

Asperi
Asperi

Reputation: 257493

Sheet has different context, so alert set up like in original code is not visible there.

Here is modified code that works. Tested with Xcode 12.1 / iOS 14.1

struct ContentView: View {
    @State private var showSheet = false
    @State var showAlert = false

    var body: some View {
        VStack {
            Text("sheet")
                .onTapGesture(perform: {
                    self.showSheet.toggle()
                })
        }
        .sheet(isPresented: $showSheet, onDismiss: { self.showAlert = true }) {
            AddView(showSheet: self.$showSheet)
        }
        .alert(isPresented: $showAlert){
            Alert(title: Text("Important message"), message: Text("Wear sunscreen"), dismissButton: .default(Text("Got it!")))
        }
    }

}
struct AddView: View {
    @Binding var showSheet: Bool

    var body: some View {
        Button("Dismiss") {
            self.showSheet = false
        }
    }
}

Upvotes: 2

Related Questions