swiftswiftuibindinguiviewrepresentable

Error in custom SwiftUI text field that can handle first responder: property is immutable


I wanted to make a custom SwiftUI text field that can handle first responder but I had this error with my code:

Cannot assign to property: '$text' is immutable

What should I do?

struct CustomTextField: UIViewRepresentable {
  class Coordinator: NSObject, UITextFieldDelegate {
    @Binding var text: String
    var didBecomeFirstResponder = false

    init(txt: Binding<String>) {
      self.$text = txt
    }

    func textFieldDidChangeSelection(_ textField: UITextField) {
      text = textField.text ?? ""
    }
  }

  @Binding var text: String
  var isFirstResponder: Bool = false

  func makeUIView(context: UIViewRepresentableContext<CustomTextField>) -> UITextField {
    let textField = UITextField(frame: .zero)
    textField.delegate = context.coordinator
    return textField
  }

  func makeCoordinator() -> CustomTextField.Coordinator {
    return Coordinator(txt: $text)
  }

  func updateUIView(_ uiView: UITextField, context: UIViewRepresentableContext<CustomTextField>) {
    uiView.text = text
    if isFirstResponder && !context.coordinator.didBecomeFirstResponder {
      uiView.becomeFirstResponder()
      context.coordinator.didBecomeFirstResponder = true
    }
  }
}

Solution

  • In beta 4, the implementation of property wrappers changed.

    Until beta 3, this was valid:

    self.$text = txt
    

    In beta 4, it changed to:

    self._text = txt
    

    Check for the difference in implementation, in this other question I posted:

    https://stackoverflow.com/a/57088052/7786555

    And for more details:

    https://stackoverflow.com/a/56975728/7786555