iosswiftuitextfielduitextfielddelegate

Keyboard dismisses on every character typed in text input in Swift


I have one textField.

private var verseTitle: UITextField = {
    let tf = UITextField()
    tf.placeholder = "TITLE"
    tf.font = UIFont(suite16: .tBlackItalic, size: 18)
    tf.textColor = .black.withAlphaComponent(0.5)
    tf.returnKeyType = .done
    tf.translatesAutoresizingMaskIntoConstraints = false
    return tf
}()

In viewDidLoad method, I have assigned self as delegate.

override func viewDidLoad() {
    super.viewDidLoad()

    self.view.backgroundColor = .white
    verseTitle.delegate = self
}

In viewDidLayout method, I'm using stack view to add textField to the view.

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()
    
    //Title
    let titleStack = UIStackView()
    titleStack.axis = .horizontal
    titleStack.alignment = .center
    titleStack.distribution = .equalSpacing
    titleStack.spacing = 8
    
    titleStack.addArrangedSubview(verseTitle)
    titleStack.addArrangedSubview(floorView)
    titleStack.translatesAutoresizingMaskIntoConstraints = false

    view.addSubview(titleStack)

    NSLayoutConstraint.activate([
        
        floorView.heightAnchor.constraint(equalToConstant: 13),
        floorView.widthAnchor.constraint(equalToConstant: 13),
        
        
        titleStack.centerXAnchor.constraint(equalTo: view.centerXAnchor),
        titleStack.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 20),
])
}

Now, the problem I'm facing is, that when I start typing in the textField, the keyboard gets dismissed only after I type one letter. I'm not sure why this is happening. I have to tap on the field after entering each letter. For some reason, the focus is taken away from the field after each letter is entered (unless I tap on a suggested autocorrect - the whole string is correctly added to the string at once)


Solution

  • What's going on here is your view, including the UITextField gets re-created after each keystroke because your view construction is in:

    viewDidLayoutSubviews(), When the bounds change for a view controller's view, the view adjusts the positions of its subviews and then the system calls this method.

    To fix it, move the code to ViewDidLoad, so the view is created only once:

    override func viewDidLoad() {
        super.viewDidLoad()
        
        self.view.backgroundColor = .white
        verseTitle.delegate = self
        
        let titleStack = UIStackView()
        titleStack.axis = .horizontal
        titleStack.alignment = .center
        titleStack.distribution = .equalSpacing
        titleStack.spacing = 8
        
        titleStack.addArrangedSubview(verseTitle)
        titleStack.translatesAutoresizingMaskIntoConstraints = false
        
        view.addSubview(titleStack)
        
        NSLayoutConstraint.activate([
            titleStack.centerXAnchor.constraint(equalTo: view.centerXAnchor),
            titleStack.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 20),
        ])
    }