首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >什么代理不能做的比反应性更好?

什么代理不能做的比反应性更好?
EN

Stack Overflow用户
提问于 2017-08-30 16:36:56
回答 1查看 744关注 0票数 3

在过去的两年里,我使用MVVM模式构建应用程序,每个教程都说MVVM使用反应库,例如: RXSwift或ReactiveCocoa,因为我是iOS程序员。我才意识到

  1. 为什么我们需要使用反应式,为什么我们不只使用委托?
  2. 什么委托不能超过反应式?
  3. 每个模式的优缺点?

我只知道Reactive是函数式编程,这意味着声明性编程。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-06-03 05:54:33

对我来说,单独使用委托似乎是实现应用程序逻辑的最长方式。响应式的方法更简洁,需要的代码更少,而且是一种非常强大的工作方式。

例如,假设您想使用RxSwift/RxCocoa和swift 4创建一个反应式ButtonTap系统:

1)创建一个协议,该协议的实现方式与创建普通委托抽象类的方式相同。请注意,我们遵循@objc

代码语言:javascript
复制
import RxSwift
import RxCocoa

// MARK: - ButtonTap Delegate protocol
@objc public protocol ButtonTapDelegate: NSObjectProtocol {
    @objc func button(didSelect view: UIView, at index: Int)
}

2) DelegateProxyType类是响应式事件发生的地方。就像你从你的委托(ButtonTapDelegate)派生一个类一样,这个类不仅可以做到这一点,而且还可以使用PublishSubject来处理你的委托消息。

代码语言:javascript
复制
// MARK: - ButtonTap DelegateProxy
open class ButtonTapDelegateProxy: DelegateProxy<UIView, ButtonTapDelegate>,
DelegateProxyType, ButtonTapDelegate {

    /// Typed parent object.
    public weak private(set) var buttonView: UIView?

    internal var didSelectSubject = PublishSubject<(view: UIView, index: Int)>()

    // MARK: - parent object for delegate proxy.
    public init(parentObject: UIView) {
        self.buttonView = parentObject
        super.init(parentObject: parentObject, delegateProxy: ButtonTapDelegateProxy.self)
    }

    // MARK: - Register known implementationss. (from DelegateProxyType)
    public static func registerKnownImplementations() {
        self.register { ButtonTapDelegateProxy(parentObject: $0) }
    }

    // MARK: - read the current delegate. (from DelegateProxyType)
    public class func currentDelegate(for object: UIView) -> ButtonTapDelegate? {
        return object.delegate
    }

    // MARK: - set the current delegate. (from DelegateProxyType)
    public class func setCurrentDelegate(_ delegate: ButtonTapDelegate?, to object: UIView) {
        object.delegate = delegate as? ButtonTapDelegateProxy
    }

    // MARK: delegate method
    public func button(didSelect view: UIView, at index: Int) {
        didSelectSubject.onNext((view, index))
    }

    // MARK: - dispose the publish subject 
    deinit {
        didSelectSubject.on(.completed)
    }
}

3)然后,简单地创建您的自定义按钮类,其中您有委托属性。您可以简单地通过调用其抽象方法将消息传递给您的委托。

代码语言:javascript
复制
// MARK: - create Custom ButtonView class with the delegate property
open class ButtonView: UIView {
    @IBOutlet weak open var delegate: ButtonTapDelegate?

    func tapButtonAction() {
        let view = UIView()
        let index = 2
        delegate.button(didSelect: view, at: index)
    }

}

// MARK: - ButtonView must have delegate property
extension ButtonView: HasDelegate {
    public typealias Delegate = ButtonTapDelegate
}

4)您可以使用RxCocoa捕获由您的代理发送的消息。您只需要使用视图的这个扩展(ButtonView)从DelegateProxy类中引用您的PublishSubject。请注意,扩展是反应式的。

代码语言:javascript
复制
// MARK: - Custom ButtonView with the Reactive delegate and its protocol function
 public extension Reactive where Base: ButtonView {

    /// Reactive wrapper for `delegate`.
    /// For more information take a look at `DelegateProxyType` protocol documentation.
    fileprivate var delegate: ButtonTapDelegateProxy {
        return ButtonTapDelegateProxy.proxy(for: base)
    }

    public func setDelegate(_ delegate: ButtonTapDelegate) -> Disposable {
        return ButtonTapDelegateProxy
        .installForwardDelegate(delegate, retainDelegate: false, onProxyForObject: self.base)
    }

    public var didSelect: ControlEvent<(view: UIView, index: Int)> {
        return ControlEvent(events: delegate.didSelectSubject)
    }
}

5)在您的ViewController中,您可以使用RxSwift监听任何按钮点击,并在DelegateProxy类中捕获由PublishSubject发送的那些事件。这与RxSwift手势示例没有什么不同:https://github.com/RxSwiftCommunity/RxGesture

代码语言:javascript
复制
class myViewController: UIViewController {

    @IBOutlet weak var buttonView: ButtonView!

    override func viewDidLoad() {
         super.viewDidLoad

         buttonView.rx.didSelect.asObservable()
            .subscribe(onNext: { view, index in
             // button tapped in view at index
        }).disposed(by: bag)
    }

}

这个过程非常类似于所有的RxSwift和RxCocoa响应式委托的工作方式,它们已经在许多UIKit元素上实现了,比如:https://github.com/ReactiveX/RxSwift/tree/master/RxCocoa/iOS

反应式是非常灵活和强大的,不需要一直调用委托方法和设置委托。这只会发生一次,想象一下如何在viewController中处理CustomViews的不同组合。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/45955694

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档