【问题标题】:SwiftUI @Binding didn't update display alertSwiftUI @Binding 没有更新显示警报
【发布时间】:2020-11-10 16:46:23
【问题描述】:

我试图在关闭工作表后显示警报。但是当我更新工作表中的@Binding 时,主页中的警报没有出现。我不知道现在有什么问题。谁能给我解释一下?是使用@Binding 的问题吗?如果这样做的方法/逻辑是错误的,我应该使用什么方法?

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
        }
    }
}

【问题讨论】:

    标签: swiftui


    【解决方案1】:

    Sheet 具有不同的上下文,因此在原始代码中设置的警报在此处不可见。

    这里是修改后的代码。使用 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
            }
        }
    }
    

    【讨论】:

    • 感谢您的评论。如果我想更改工作表中的 showAlert 怎么办?像任何东西触发的东西,但不仅仅是解雇?
    • 正如我写的那样,工作表具有不同的视图层次结构上下文,并且您不能像在原始帖子中那样显示附加在工作表视图层次结构之外的警报。您可以轻松地对此进行测试 - 而不是关闭按钮上的工作表只是尝试显示警报...因此,如果您需要在工作表上显示警报,则必须在 AddView 中使用不同的警报修饰符。
    【解决方案2】:

    真正的问题是您试图关闭工作表并同时显示警报。在您的代码中,如果您向警报添加 0.5 秒的延迟,它将起作用:

    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
                    }
                }
            }
        }
    

    不过,这样写更简洁:

    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()
            }
        }
    }
    

    【讨论】:

    • 感谢您的评论。我可以知道为什么必须延迟它吗?你能解释一下吗?谢谢。
    • 我不知道技术答案。当您尝试同时显示 2 个东西(警报、ActionSheets、Sheets、FullScreenCovers 等)时,这经常在 SwiftUI 中发生。 Xcode 似乎对屏幕上显示的视图感到困惑。我相信在这里,您试图在第一个屏幕上显示警报,而用户在第二个屏幕上,并且由于 Xcode 知道您在第二个屏幕上,它不会在背景屏幕上显示警报。通过延迟 0.5 秒,您可以让第二个屏幕有时间关闭,因此当您尝试显示警报时,它已经在前台屏幕上。
    猜你喜欢
    • 2021-08-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-05
    • 2021-04-02
    相关资源
    最近更新 更多