Swift:带TextField的Alert关闭后自动闪显问题的解决方法
解决SwiftUI带TextField的Alert关闭后闪显的问题
这个闪显问题的核心原因是状态更新的时序冲突:当点击Alert的按钮时,presentAlert被设为false的同时,username或绑定的usernameToSave更新触发了视图重渲染,导致Alert短暂重新出现。以下是几种可行的修复方案:
方案一:延迟更新绑定值
利用DispatchQueue.main.async让赋值操作在Alert关闭的视图更新完成后执行,避免触发额外重渲染:
Button("Login", action: { DispatchQueue.main.async { usernameToSave = username } })
方案二:监听Alert状态变化后更新
通过.onChange监听presentAlert的状态,只有当Alert完全关闭(presentAlert变为false)时,再更新绑定的usernameToSave:
struct ContentView: View { @State private var presentAlert = false @State private var username: String = "" @Binding var usernameToSave: String var body: some View { Button("Show Alert") { presentAlert = true } .alert("Login", isPresented: $presentAlert, actions: { TextField("Username", text: $username) Button("Login", action: {}) Button("Cancel", role: .cancel, action: {}) }, message: { Text("Please enter your username and password.") }) .onChange(of: presentAlert) { newValue in if !newValue { usernameToSave = username } } } }
方案三:先取消TextField焦点
使用@FocusState管理TextField的焦点,在点击按钮关闭Alert时先取消焦点,避免焦点变化触发的UI更新干扰Alert关闭流程:
struct ContentView: View { @State private var presentAlert = false @State private var username: String = "" @Binding var usernameToSave: String @FocusState private var isUsernameFocused: Bool var body: some View { Button("Show Alert") { presentAlert = true } .alert("Login", isPresented: $presentAlert, actions: { TextField("Username", text: $username) .focused($isUsernameFocused) Button("Login", action: { isUsernameFocused = false usernameToSave = username }) Button("Cancel", role: .cancel, action: { isUsernameFocused = false }) }, message: { Text("Please enter your username and password.") }) } }
以上方案的核心都是让状态更新的时序与Alert关闭动作同步,避免在Alert关闭过程中触发不必要的视图重渲染,从而消除闪显问题。
内容的提问来源于stack exchange,提问作者May
相关产品推荐
相关产品推荐

