SwiftUI中SecureField失焦后重新输入值重置问题求助
问题
在SwiftUI里用Group配合if/else切换SecureField和TextField实现密码显隐,TextField一切正常,但SecureField在隐藏状态下,输入内容后失焦,再次聚焦输入时值会被重置。哪怕删掉TextField只留SecureField,问题还是存在。用的是Environment里ViewModel的@Published变量password,给变量加了didSet后控制台日志显示:首次输入“aaaa”打印两次,点上方TextField又打印两次;再点SecureField没输出,再输入“a”时打印最后四行。
代码如下:
Group{ if (!loginViewModel.showPassword) { SecureField("password".localizableString(appViewModel.language), text: $loginViewModel.password) }else { TextField("password".localizableString(appViewModel.language), text: $loginViewModel.password) .autocapitalization(.none) .padding(.vertical, -0.75) } } .disableAutocorrection(true) .padding(.vertical, -2) .modifier(PlaceholderStyle(showPlaceHolder: loginViewModel.password.isEmpty, placeholder: "password".localizableString(appViewModel.language))) .foregroundColor(Color("TextDefault")) .keyboardType(.emailAddress)
原因
这不是SecureField的默认行为,问题出在用if/else切换两个输入控件时,每次状态变化(包括聚焦/失焦)会触发视图销毁重建,SecureField重新初始化时没法正确保留绑定的password值。另外自定义的PlaceholderStyle如果依赖password.isEmpty状态,也可能加重这个问题。
解决办法
办法1:用iOS 15+的secure(_:)修饰符(推荐)
不用切换两个输入框,直接用同一个TextField,通过secure(_:)控制是否隐藏密码,这样视图不会反复重建,状态绑定更稳:
TextField("password".localizableString(appViewModel.language), text: $loginViewModel.password) .autocapitalization(.none) .disableAutocorrection(true) .padding(.vertical, -2) .modifier(PlaceholderStyle(showPlaceHolder: loginViewModel.password.isEmpty, placeholder: "password".localizableString(appViewModel.language))) .foregroundColor(Color("TextDefault")) .keyboardType(.emailAddress) .secure(!loginViewModel.showPassword) // 核心:控制密码显隐
办法2:兼容iOS 15以下
要是得支持低版本,给两个输入框加固定的id,避免视图重建丢失状态:
Group{ if (!loginViewModel.showPassword) { SecureField("password".localizableString(appViewModel.language), text: $loginViewModel.password) .id("password-secure") // 固定id }else { TextField("password".localizableString(appViewModel.language), text: $loginViewModel.password) .autocapitalization(.none) .padding(.vertical, -0.75) .id("password-text") // 固定id } } .disableAutocorrection(true) .padding(.vertical, -2) .modifier(PlaceholderStyle(showPlaceHolder: loginViewModel.password.isEmpty, placeholder: "password".localizableString(appViewModel.language))) .foregroundColor(Color("TextDefault")) .keyboardType(.emailAddress)
另外可以先去掉自定义的PlaceholderStyle测试,确认是不是这个修饰符导致的状态冲突;同时检查ViewModel里password的didSet逻辑,别让它在失焦时意外重置值。
内容的提问来源于stack exchange,提问作者kleo
相关产品推荐
相关产品推荐

