You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 17:15:14