SwiftUI中SecureTextField收起键盘后内容重置问题求助
解决SwiftUI中SecureTextField收起键盘后内容丢失的问题
你遇到的SecureTextField收起键盘后内容重置的问题,主要是因为它的内部绑定机制在全局收起键盘或视图刷新时,容易出现绑定值同步异常。下面提供两种可行的解决方案:
方案一:用内部状态缓存输入内容
通过在自定义PasswordTextField内部维护一个独立的状态变量,和SecureField直接绑定,再双向同步到外部的绑定值,避免SecureField直接操作外部绑定导致的异常。
修改后的PasswordTextField代码:
struct PasswordTextField: View { var placeHolder:String var image:String? var label:String @Binding var text:String @FocusState private var isTextFieldFocused:Bool // 内部状态保存输入内容,避免直接绑定外部值的异常 @State private var internalText: String = "" var body: some View { VStack(alignment: .leading,spacing: 4) { if !label.isEmpty { Text(label).customFont(Font.poppinsMedium, size: 15) .foregroundStyle(Color.appTextBlackColor) } HStack { SecureField("", text: $internalText) .placeholder(when: internalText.isEmpty, placeholder: { Text(placeHolder).foregroundStyle(Color.appPlaceholderColor) }) .focused($isTextFieldFocused) .autocorrectionDisabled(true) .textInputAutocapitalization(.none) .font(.custom(Font.poppinsMedium, size: 14)) .foregroundStyle(Color.appTextBlackColor) .padding([.leading],16) .frame(height: 45) // 同步内部输入到外部绑定值 .onChange(of: internalText) { newValue in text = newValue } // 初始化时同步外部值到内部状态 .onAppear { internalText = text } if let image { Image(image) .resizable() .scaledToFit() .foregroundStyle(Color.appBorderColor) .padding() } } .frame(height: 50) .background( RoundedRectangle(cornerSize: CGSize(width: 8, height: 8)) .stroke(isTextFieldFocused ? Color.appPinkColor : Color.appBorderColor,lineWidth: 2) ) } .foregroundStyle(Color.appPlaceholderColor) .onTapGesture { isTextFieldFocused = true } // 外部绑定值变化时同步到内部状态 .onChange(of: text) { newValue in internalText = newValue } } }
方案二:用@FocusState统一管理焦点
放弃使用UIApplication.shared.endEditing()这种全局收起键盘的方式,改用SwiftUI原生的@FocusState来管理输入框的焦点状态,更符合SwiftUI的响应式范式,也能避免全局操作带来的异常。
修改后的父视图代码:
struct ParentView: View { @State private var phone: String = "" @State private var password:String = "" // 定义枚举管理各个输入框的焦点 enum FocusedField { case phone, password } @FocusState private var focusedField: FocusedField? var body: some View { VStack(spacing:20){ CustomTextField(placeHolder: "Phone Number", image: "mobile", label: "Phone", text: $phone) .keyboardType(.numberPad) .focused($focusedField, equals: .phone) .onChange(of: phone) { newValue in if newValue.count >= 10 { focusedField = nil // 清空焦点,自动收起键盘 phone = String(newValue.prefix(10)) } } PasswordTextField( placeHolder: "Password", image: "password", label: "Password", text: $password ) .focused($focusedField, equals: .password) } .onTapGesture { focusedField = nil // 点击外部清空所有焦点 } } }
如果采用方案二,可直接将PasswordTextField内部的@FocusState private var isTextFieldFocused:Bool替换为外部传入的焦点绑定,保持全局焦点管理的一致性。
两种方案结合使用效果最佳,既能避免绑定值异常,又能规范焦点管理。
内容的提问来源于stack exchange,提问作者sangam pokharel
相关产品推荐
相关产品推荐

