rx-swiftrx-cocoa

Why is the action of 'tapping a button' also considered an asynchronous event?


While studying RxSwift, I came across a question. Code like button.rx.tap is also referred to as an asynchronous event, but why can it be considered an 'asynchronous event'? Typically, when we think of 'asynchronous,'

we think of network communication or disk IO, but UI responses like tapping a button are processed on the main thread, right? It's difficult to precisely understand the meaning of 'asynchronous events' as described in RxSwift's definition. Could you please explain? Thank you.

button.rx.tap
    .throttle(RxConst.delay, schedulers: Schedulers.main)
    .bind(onNext: { print("Button Tapped") })
    .disposed(by: disposeBag)

Solution

  • In synchronous code, a function doesn't get called until the previous function completes. So for example:

    funcA()
    funcB()
    

    The second function will not initiate until after the first one completes.

    When using Rx, this isn't necessarily the case.

    buttonA.rx.tap().debug("buttonA").subscribe()
    buttonB.rx.tap().debug("buttonB").subscribe()
    

    With the above, the tap associated with buttonB will be executed even though the tap associated with buttonA is still active.

    This lets you do intersting things like work with the UI the same way you work with network code. For example:

    extension UIViewController {
        func displayInformationAlert(title: String) -> (String) -> Observable<Void> {
            { [weak self] message in
                Observable.create { observer in
                    let alert = UIAlertController(title: title, message: message, preferredStyle: .alert)
                    alert.addAction(UIAlertAction(title: "OK", style: .default) { _ in
                        observer.onNext(())
                        observer.onCompleted()
                    })
                    self?.present(alert, animated: true, completion: nil)
                    return Disposables.create {
                        if !alert.isBeingDismissed { self?.dismiss(animated: true) }
                    }
                }
            }
        }
    }
    

    You can use the above in an Observable chain with a flatMap just like you do network requests.