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