How to obtain a UIAlertController observable (ReactiveCocoa or RxSwift)?
Solution, that allows to keep all code in one place, is extension
to UIAlertViewController
:
extension UIAlertController {
struct AlertAction {
var title: String?
var style: UIAlertActionStyle
static func action(title: String?, style: UIAlertActionStyle = .default) -> AlertAction {
return AlertAction(title: title, style: style)
}
}
static func present(
in viewController: UIViewController,
title: String?,
message: String?,
style: UIAlertControllerStyle,
actions: [AlertAction])
-> Observable<Int>
{
return Observable.create { observer in
let alertController = UIAlertController(title: title, message: message, preferredStyle: style)
actions.enumerated().forEach { index, action in
let action = UIAlertAction(title: action.title, style: action.style) { _ in
observer.onNext(index)
observer.onCompleted()
}
alertController.addAction(action)
}
viewController.present(alertController, animated: true, completion: nil)
return Disposables.create { alertController.dismiss(animated: true, completion: nil) }
}
}
}
And usage:
let actions: [UIAlertController.AlertAction] = [
.action(title: "no", style: .destructive),
.action(title: "yes")
]
UIAlertController
.present(in: self, title: "Alert", message: "message", style: .alert, actions: actions)
.subscribe(onNext: { buttonIndex in
print(buttonIndex)
})
.disposed(by: bag)
Code and logic is pretty straightforward, so i provide you no explanation here. Ask if you have any questions.
I was looking for a nice way to user AlertController in a Reactive way and this post helped me.
I used the solution of Pacification but I had to update it to be able to return a generic value instead of an index. I also adapted the syntax to swift 4.
I post it here in case someone is interested.
extension UIAlertController {
struct Action<T> {
var title: String?
var style: UIAlertAction.Style
var value: T
static func action(title: String?, style: UIAlertAction.Style = .default, value: T) -> Action {
return Action(title: title, style: style, value: value)
}
}
static func present<T>(in viewController: UIViewController,
title: String? = nil,
message: String? = nil,
style: UIAlertController.Style,
actions: [Action<T>]) -> Observable<T> {
return Observable.create { observer in
let alertController = UIAlertController(title: title, message: message, preferredStyle: style)
actions.enumerated().forEach { index, action in
let action = UIAlertAction(title: action.title, style: action.style) { _ in
observer.onNext(action.value)
observer.onCompleted()
}
alertController.addAction(action)
}
viewController.present(alertController, animated: true, completion: nil)
return Disposables.create { alertController.dismiss(animated: true, completion: nil) }
}
}
}
Regards