uitextfieldrx-swiftrx-cocoa

How to navigate through UITextFields (Next / Done Buttons) with Rx


How can you navigate through textfields with the next / done keyboard buttons, only using RxSwift + RxCocoa?


Solution

  • With a simple UITextField extension you can observe the textfield's control events and act accordingly.

    Extension:

    import UIKit
    import RxSwift
    import RxCocoa
    
    extension UITextField {
      func resignWhenFinished(_ disposeBag: DisposeBag) {
        setNextResponder(nil, disposeBag: disposeBag)
      }
    
      func setNextResponder(_ nextResponder: UIResponder?, disposeBag: DisposeBag) {
        // Set the return key type to:
        //   - next: When there is a next responder
        //   - done: When there is no next responder (simply resign)
        returnKeyType = (nextResponder != nil) ? .next : .done
    
        // Subscribe on editing end on exit control event
        rx.controlEvent(.editingDidEndOnExit)
          .subscribe(onNext: { [weak self, weak nextResponder] in
            if let nextResponder = nextResponder {
              // Switch to next responder if available
              nextResponder.becomeFirstResponder()
            } else {
              // Otherwise simply resign
              self?.resignFirstResponder()
            }
          })
          .addDisposableTo(disposeBag)
      }
    }
    

    Usage:

    @IBOutlet private weak var firstTextField: UITextField!
    @IBOutlet private weak var secondTextField: UITextField!
    @IBOutlet private weak var lastTextField: UITextField!
    private let disposeBag = DisposeBag()
    
    override func viewDidLoad() {
      super.viewDidLoad()
    
      firstTextField.setNextResponder(secondTextField, disposeBag: disposeBag)
      secondTextField.setNextResponder(lastTextField, disposeBag: disposeBag)
      lastTextField.resignWhenFinished(disposeBag)
    }