iosswiftrx-swift

How to call debounce on RxKeyboard instance with RxSwift?


This is what I simply have in my code:

RxKeyboard.instance.visibleHeight.drive(onNext: { [weak self] value in
    // do something with value
}).disposed(by: disposeBag)

but this is called twice with values: 291, 336. And because of this my view jumps. It happens just when I focus on UITextField. Keyboard is already on the screen, but it is called twice. Why? Is there a way to remove it? I thought it will be possible with:

.debounce(.milliseconds(100), scheduler: MainScheduler.instance)

but it will not work with RxKeyboard.


Solution

  • This issue is suspicious, since RxKeyboard used UIResponder.keyboardFrameEndUserInfoKey to get the keyboard frame, the KVO will give you the final height of the keyboard. I've tried to reproduce but no luck, it seems like the keyboard somehow had been toggled Predictive on Setting.

    However, you may want to try these workarounds.

    1. Using debounce as your original question:
    RxKeyboard.instance.visibleHeight
        .asObservable()
        .debounce(.milliseconds(300), scheduler: MainScheduler.instance)
        .subscribe(onNext: { height in
            ...
        })
        .disposed(by: disposeBag)
    
    1. The KVO fired twice so you can simply ignore the first one.
    RxKeyboard.instance.visibleHeight
        .asObservable()
        .skip(1)
        .observe(on: MainScheduler.instance)
        .subscribe(onNext: { height in
            ...
        })
        .disposed(by: disposeBag)