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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 11:44:49