• iOS代理一对一秒变一对多--RxSwift delegateProxy使用


         委托代理(delegate) iOS 开发中十分常见。不管是使用系统自带的库,还是一些第三方组件时,我们总能看到 delegate 的身影。使用 delegate 可以实现代码的松耦合,减少代码复杂度。但如果我们项目中使用 RxSwift,那么原先的 delegate 方式与我们链式编程方式就不相称了。

        解决办法就是将代理方法进行一层 Rx 封装,这样做不仅会减少许多不必要的工作(比如原先需要遵守不同的代理,并且要实现相应的代理方法),还会使得代码的聚合度更高,更加符合响应式编程的规范。

        其实在 RxCocoa 源码中我们也可以发现,它已经对标准的 Cocoa 做了大量的封装(比如 tableView 的 itemSelected)。下面我将通过样例演示如何将代理方法进行 Rx 化。

    一、对 Delegate进行Rx封装原理

    1,DelegateProxy

    (1)DelegateProxy 是代理委托,我们可以将它看作是代理的代理。

    (2)DelegateProxy 的作用是做为一个中间代理,他会先把系统的 delegate 对象保存一份,然后拦截 delegate的方法。也就是说在每次触发 delegate 方法之前,会先调用 DelegateProxy 这边对应的方法,我们可以在这里发射序列给多个订阅者。

    2,流程图

    这里以 UIScrollView 为例,Delegate proxy 便是其代理委托,它遵守 DelegateProxyType 与 UIScrollViewDelegate,并能响应 UIScrollViewDelegate 的代理方法,这里我们可以为代理委托设计它所要响应的方法(即为订阅者发送观察序列)。

    /***
      
     +-------------------------------------------+
     |                                           |
     | UIView subclass (UIScrollView)            |
     |                                           |
     +-----------+-------------------------------+
                 |
                 | Delegate
                 |
                 |
     +-----------v-------------------------------+
     |                                           |
     | Delegate proxy : DelegateProxyType        +-----+---->  Observable<T1>
     |                , UIScrollViewDelegate     |     |
     +-----------+-------------------------------+     +---->  Observable<T2>
                 |                                     |
                 |                                     +---->  Observable<T3>
                 |                                     |
                 | forwards events                     |
                 | to custom delegate                  |
                 |                                     v
     +-----------v-------------------------------+
     |                                           |
     | Custom delegate (UIScrollViewDelegate)    |
     |                                           |
     +-------------------------------------------+
     
     **/
    二 自定义代理实现代理的一对多
    1实现一个需要代理的类
    //
    //  Car.swift
    //  Pod11
    //
    //  Created by dzq_mac on 2020/1/13.
    //  Copyright © 2020 dzq_mac. All rights reserved.
    //
    
    import UIKit
    import RxSwift
    import CoreLocation
    
     @objc public protocol CarOilProtocol: AnyObject {
        @discardableResult
        func oil80(name:String) -> String
        @discardableResult
        func oil50(name:String) -> String
    //    func oil20(whoCar:String)
    //    func oil10(whoCar:String)
    }
    extension CarOilProtocol {
        public func oil10(whoCar:String){
    
        }
        public func oil20(whoCar:String){
            
        }
    }
    public class CarCar:ReactiveCompatible {
        
        var name :String
        var oilQulity:Int32 = 100
        var disposeBag:DisposeBag = DisposeBag()
        var timer :Observable<Int>?
        public weak var delegate:CarOilProtocol?
        
        init(name:String) {
            self.name = name
        }
        
        func startRun(){
            timer =  Observable<Int>.interval(1, scheduler: MainScheduler.instance)
            
            timer?.subscribe(onNext: {[weak self] (i) in
    //            print(i)
                self?.oilQulity -= 1
                if self?.oilQulity == 80 {
                     self?.delegate?.oil80(name: self?.name ?? "")
    
                    
                }else if self?.oilQulity == 50 {
                    self?.delegate?.oil50(name: self?.name ?? "")
    
                }else{
                    
                }
                
            }).disposed(by: disposeBag)
            
        }
    }
    

     2.首先我们继承 DelegateProxy 创建一个关于上述类代理委托,同时它还要遵守 DelegateProxyType 和 CarOilProtocol协议。

    //
    //  CarCarOilProtocol.swift
    //  Pod11
    //
    //  Created by dzq_mac on 2020/1/13.
    //  Copyright © 2020 dzq_mac. All rights reserved.
    //
    
    import UIKit
    import RxSwift
    import RxCocoa
    import CoreLocation
    
    extension CarCar :HasDelegate{
        public typealias Delegate = CarOilProtocol
        
    }
    public class RxCarCarOilProtocolProxy: DelegateProxy<CarCar,CarOilProtocol>,DelegateProxyType,CarOilProtocol {
      
        public init(car:CarCar) {
            super.init(parentObject: car, delegateProxy: RxCarCarOilProtocolProxy.self)
        }
        public static func registerKnownImplementations() {
            self.register { RxCarCarOilProtocolProxy(car: $0)}
        }
        
        internal lazy var oil80Subject = PublishSubject<String>()
        internal lazy var oil50Subject = PublishSubject<String>()
    
        public func oil80(name: String) -> String {
           let nn = _forwardToDelegate?.oil80(name: name)//原来的代理
            oil80Subject.onNext(name)
            return  nn ?? name
        }
    
        public func oil50(name: String) -> String {
            let mm = _forwardToDelegate?.oil50(name: name)
            oil50Subject.onNext(name)
            return mm ?? name
        }
    
    
        deinit {
            self.oil80Subject.on(.completed)
            self.oil50Subject.on(.completed)
        }
    
    }
    

     3.接着我们对 Carcar 进行Rx 扩展,作用是将Carcar与前面创建的代理委托关联起来,将相关的 delegate 方法转为可观察序列。

    //
    //  CarCar+rx.swift
    //  Pod11
    //
    //  Created by dzq_mac on 2020/1/13.
    //  Copyright © 2020 dzq_mac. All rights reserved.
    //
    
    import UIKit
    import RxSwift
    import RxCocoa
    
    extension Reactive where Base:CarCar{
        public var  delegate:DelegateProxy<CarCar,CarOilProtocol>{
            return RxCarCarOilProtocolProxy.proxy(for: base)
        }
        
        public var dao80:Observable<String>{
            return RxCarCarOilProtocolProxy.proxy(for: base).oil80Subject.asObserver()
    //        let source = delegate.methodInvoked(#selector(CarOilProtocol.oil80(name:)))
    //            .map{ s in
    //                
    //                return try castOrThrow1(String.self,s[1])
    //        }
    //        return source
            
        }
        
        public var dao50:Observable<String>{
            return RxCarCarOilProtocolProxy.proxy(for: base).oil50Subject.asObserver()
        }
        
        public func setDelegate(_ delegate:CarOilProtocol) -> Disposable{
            return RxCarCarOilProtocolProxy.installForwardDelegate(delegate, retainDelegate: false, onProxyForObject: self.base)
        }
        
        
        
    }
    

    4在其他地方就可以像一般的RxSwift一样订阅这个序列了

    var car : CarCar!
        override func viewDidLoad() {
            super.viewDidLoad()
            self.view.backgroundColor = UIColor.white
            
            car = CarCar(name: "beijing")
            car.delegate = self
            car.startRun()
            car.rx.dao80.asObservable().subscribe({ (str) in
                print("rx80--" + (str.element ?? ""))
            }).disposed(by: disposeBag)
    
        }
    

    这样写,本来的代理的代理方法也会走,rx订阅的方法也会走,就实现了从单一代理到多代理的转化,RxSwift框架还是非常强大的,继续学习,有兴趣的可以一起交流啊!



  • 相关阅读:
    常用数据库种类 以及优缺点
    数据库
    Python中os与sys两模块的区别
    python操作数据库
    python——解释型语言
    面向对象的三大特性
    Android Fastboot 与 Recovery 和刷机 千山万水迷了鹿
    selenium与appium怎样联系
    Pycharm快捷键
    uiautomator python版本
  • 原文地址:https://www.cnblogs.com/duzhaoquan/p/12195711.html
Copyright © 2020-2023  润新知