如何获取可观察到的UIAlertController(ReactiveCocoa或RxSwift)? [英] How to obtain a UIAlertController observable (ReactiveCocoa or RxSwift)?

查看:70
本文介绍了如何获取可观察到的UIAlertController(ReactiveCocoa或RxSwift)?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我实现了一个反应性" UIAlertController ,因此我可以获得按钮按下的 Observable< Int> .(请参见下面的代码).

I implemented a "reactive" UIAlertController so I can get an Observable<Int> of the button press. (See code below).

我的一个或多个问题是:

My question, or questions, are:

  • 此实现是否正确?我不喜欢存放观察员;我想知道是否有更好的解决方案.
  • 或者...在ReactiveCocoa或RxSwift中是否已经有此实现?

这里是实现.我删除了与问题无关的部分.

Here is the implementation. I removed the parts not relevant to te question.

class AlertBuilder {

    typealias AlertAction = (Int) -> ()

    private let alert: UIAlertController

    /** If observable() is called, we keep here the observers to notify them */
    private var observers: [AnyObserver<Int>] = []

    init(alert: UIAlertController) {
        self.alert = alert
    }

    /** When using observable(), the action is not needed. */
    func button(_ title: String, style: UIAlertActionStyle = .default, action: AlertAction? = nil) -> AlertBuilder {

        let buttonIndex = alert.actions.count
        alert.addAction( UIAlertAction(title: title, style: style, handler: { [weak self] _ in

            // Callback via action
            action?(buttonIndex)

            // Callback via observers
            if let this = self {
                for observer in this.observers {
                    observer.onNext(buttonIndex)
                    observer.onCompleted()
                }
                this.observers = []
            }
        }) )
        return self
    }

    /**
     * Returns an Observable that will emit the pressed button index and complete.
     * It's important to keep a reference to the AlertBuilder, otherwise the events won't be received.
     */
    func observable() -> Observable<Int> {

        return Observable<Int>.create { observer in
            self.observers.append(observer)
            return Disposables.create()
        }
    }
}

您可以从控制器中使用它,如下所示:

You would use it from a controller, like this:

let alert = UIAlertController(title: "title", message: "msg", preferredStyle: .actionSheet)

let builder = AlertBuilder(alert: alert)
    .button("no", style: .destructive)
    .button("yes")

self.present(alert, animated: true, completion: nil)

self.builder.observable()
    .subscribe(onNext: { buttonIndex in /* ... */ })
    .disposed(by: bag)

// keep reference to builder so observable() works
self.builder = builder

推荐答案

允许将所有代码都放在一个地方的解决方案是扩展 UIAlertViewController :

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) }
        }

    }

}

和用法:

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.

这篇关于如何获取可观察到的UIAlertController(ReactiveCocoa或RxSwift)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆