Search code examples
iosswiftuitextfielduitextfielddelegatereactivekit

UITextField resigns first responder right after I call becomeFirstResponder when I use ReactiveKit/Bond


I have a couple of UITextFields in a static tableviewcontroller. I have specified a tag value for each textfield so that when the user clicks next on the keyboard I can get the textfield with the next tag and call becomesFirstResponder so that the user would navigate between textfields.

func textFieldShouldReturn(_ textField: UITextField) -> Bool {
    let tag = textField.tag
    if let tf = self.view.viewWithTag(tag + 1) as? UITextField {
         tf.becomeFirstResponder()
     }
}

This would essentially work. However, when I use ReactiveKit/Bond, specifically when I call the following line (assuming that lastName is the next textfield) in viewdidload to bind the UI with the model:

profile.lastName.bidirectionalBind(to: lastName.reactive.text)

The next textfield (lastName) would become in edit mode for a couple of milliseconds then the keyboard is dismissed and the textfield is not in edit mode anymore.

When I comment out the bond line the logic would succeed. I have tried replacing the bidirectional bond with a 1-way bond or calling obserNext but this would cause the same problem as well.


Solution

  • After a while of searching, debugging, and playing around, I have changed the line that calls becomeFirstResponder to be dispatched asynchronously and ironically this makes it work. Yet, I have no idea why. I found this solution in the answer here (for a different reactive library).

    Updated Code:

    func textFieldShouldReturn(_ textField: UITextField) -> Bool {
       let tag = textField.tag
        if let tf = self.view.viewWithTag(tag + 1) as? UITextField {
                DispatchQueue.main.async {
                    tf.becomeFirstResponder()
                }
            }
    }