什么代表不能做反应式? [英] What delegate cant do than Reactive?

查看:46
本文介绍了什么代表不能做反应式?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

最近两年我用 MVVM 模式构建应用程序,每个教程都说 MVVM 使用 Reactive 库,例如:RXSwift 或 ReactiveCocoa 因为我是 iOS 程序员.我才意识到

in the last two years I build app with MVVM pattern, and every tutorial always says that MVVM use Reactive library, example: RXSwift or ReactiveCocoa because I am iOS programmer. I just realize

  1. 为什么我们需要使用 Reactive,为什么我们不只使用 delegate ?
  2. 什么代表不能通过 Reactive 做?
  3. 每种模式的优缺点?

我只知道 Reactive 是函数式编程,也就是声明式编程.

I just know that Reactive is Functional programming that mean declarative programming.

推荐答案

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

For me using delegate alone seems to be the longest way to implement your app logic. Going reactive is much more cleaner, requires less code and is a very powerful way of doing things.

举个例子,假设你想使用 RxSwift/RxCocoa 和 swift 4 创建一个 Reactive ButtonTap 系统:

Take for example, let say you want to create a Reactive ButtonTap system using RxSwift/RxCocoa with swift 4:

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

1) you create a protocol which is implemented the same way as you would when creating a normal delegate abstract class. Note that we are conforming to @objc

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 处理委托消息.

2) the DelegateProxyType class is where the reactive stuff happens. Just as you would have a class derive from your delegate (ButtonTapDelegate), this class not only does that but also handles your delegate messages using a PublishSubject.

// 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) 然后,只需在具有委托属性的地方创建自定义按钮类.您可以通过调用其抽象方法简单地将消息传递给您的委托.

3) then, simply create your custom button class where you have the delegate property. You can simply pass a message to your delegate by calling its abstract method.

// 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.请注意,扩展是响应式的

4) you can capture that message sent by your delegate using RxCocoa. You would simply need to refer back to your PublishSubject from your DelegateProxy class using this extension of your view (ButtonView). Note that the extension is Reactive

// 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

5) in your ViewController, you would listen to any button tap using RxSwift and capture those events sent by the PublishSubject in your DelegateProxy class. this is not different from the RxSwift gestures examples: https://github.com/RxSwiftCommunity/RxGesture

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 Reactive 代理的工作方式非常相似,他们已经在许多 UIKit 元素上实现了这些:https://github.com/ReactiveX/RxSwift/tree/master/RxCocoa/iOS

This process is very similar to how all the RxSwift and RxCocoa Reactive delegates work, which they have implemented on many UIKit elements like so: https://github.com/ReactiveX/RxSwift/tree/master/RxCocoa/iOS

Reactive 非常灵活和强大,不需要一直调用委托方法和设置委托.这只会发生一次,想象一下如何在 viewController 中处理自定义视图的不同组合.

Going reactive is just very flexible and powerful, there is no need to call delegate methods and set delegates all the time. This only happens once and just imagine the different combinations of how to handle your CustomViews inside your viewController.

这篇关于什么代表不能做反应式?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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