Skip to content

Instantly share code, notes, and snippets.

@andschdk
Last active March 14, 2019 01:02
Show Gist options
  • Save andschdk/578afffeb375f5db7bb11e8a8443de82 to your computer and use it in GitHub Desktop.
Save andschdk/578afffeb375f5db7bb11e8a8443de82 to your computer and use it in GitHub Desktop.
Simple protocol to ensure only one item is presented at a time. It is based on the Rx `.zip` operator. As an example it is used for presenting alerts one at a time. This is great when dealing with arbitrary number of alerts that can appear because of uncontrollable factors such as errors.
import RxSwift
public protocol SerialPresenter {
associatedtype T
var incoming: Observable<T> { get }
var dismissCurrent: Observable<Void> { get }
var present: Observable<T> { get }
}
public extension SerialPresenter {
var present: Observable<T> {
return Observable.zip(
incoming,
dismissCurrent.startWith(())
) { content, _ in content }
}
}
import UIKit
import RxSwift
import RxOptional
import SerialPresenter
class ViewController: UIViewController {
private var presentAlert: Observable<UIAlertController>!
private let dismissAlert = PublishSubject<Void>()
private let bag = DisposeBag()
override func viewDidLoad() {
super.viewDidLoad()
let alertOne = Observable.just(())
.delay(5, scheduler: MainScheduler.instance)
.map { [weak self] _ in self?.createAlert(with: "Alert 1") }
.filterNil()
let alertTwo = Observable.just(())
.delay(10, scheduler: MainScheduler.instance)
.map { [weak self] _ in self?.createAlert(with: "Alert 2") }
.filterNil()
let alertThree = Observable.just(())
.delay(10, scheduler: MainScheduler.instance)
.map { [weak self] _ in self?.createAlert(with: "Alert 3") }
.filterNil()
presentAlert = Observable.merge(
alertOne,
alertTwo,
alertThree
)
present
.subscribe(onNext: { [weak self] vc in
self?.present(vc, animated: true, completion: nil)
})
.disposed(by: bag)
}
private func createAlert(with title: String) -> UIAlertController {
let dismissAction = UIAlertAction(title: "OK", style: .cancel) { [weak self] _ in
self?.dismissAlert.onNext(())
}
let vc = UIAlertController(title: title, message: nil, preferredStyle: .alert)
vc.addAction(dismissAction)
return vc
}
}
extension ViewController: SerialPresenter {
typealias T = UIAlertController
var incoming: Observable<UIAlertController> {
return presentAlert
}
var dismissCurrent: Observable<Void> {
return dismissAlert
}
}
@andschdk
Copy link
Author

GIF

demo

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment