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框架还是非常强大的,继续学习,有兴趣的可以一起交流啊!

原文地址:https://www.cnblogs.com/duzhaoquan/p/12195711.html

时间: 2024-10-08 23:10:49

iOS代理一对一秒变一对多--RxSwift delegateProxy使用的相关文章

iOS代理模式

iOS代理模式的简单理解:当一个对象无法直接获取到另一个对象的指针,又希望对那个变量进行一些操作时,可以使用代理模式. 代理主要由三部分组成: (1)协议:用来指定代理双方可以做什么,必须做什么. (2)代理:根据指定的协议,完成委托方需要实现的功能. (3)委托:根据指定的协议,指定代理去完成什么功能. 代理使用步骤 1.申明一个协议  (这个写在需要被获取的对象里面,也可以单独写一个类) @protocol TextDelegate -(void)deliverFirsttext:(NSSt

oracle数据库 将秒变为时:分:秒

下列方法只适合在一天之内的秒数 select to_char(trunc(sysdate)+27994/(60*60*24),'hh24:mi:ss') from dual; 结果为:07:46:34 oracle数据库 将秒变为时:分:秒

华科云VMware瘦客户机秒变“超级英雄”,神助力商务办公

华科云VMware瘦客户机秒变“超级英雄”http://www.sharevdi.cn/index.php?a=shows&catid=40&id=50,服务热线:4006683769,神助力商务办公.每个人心中都有一位超级英雄,就像美国漫画中最主旋律的美国队长一样!在科技飞速发展的今日,人们的生活节奏越来越快,忙碌的工作让我们渴望着能够分分钟化身“美国队长”,拥有人类巅峰的体能,超强的能力和惊人的速度.然而,美国队长只是漫画家笔下的一位人物,你还是你,需要在工作中奔波的你,但华科云VMw

恭喜你!2018年秒变程序员不再是梦!

我们的生活中出现了很多小程序程序员的重要性也提现出来了,很多人都很崇拜程序员,觉得ta们很厉害,高深莫测的,好像无所不能一样.如果你也想成为这样的人,那么,恭喜你!中奖了!2018年我们一起来实现这个梦想吧! 很多人都在问小程序有什么优势??????我们为什么要开发小程序?????如何快速开发小程序?????. . . . . . 小程序有以下优势1.小程序不需要下载和安装--省时省力省空间 方便王能--随时随地只需要打开就能用,用完了就离开,.2.流量大--微信有9亿多的用户,这也给小程序引入

你真的了解iOS代理设计模式吗?

OS中消息传递方式 在iOS中有很多种消息传递方式,这里先简单介绍一下各种消息传递方式. 通知:在iOS中由通知中心进行消息接收和消息广播,是一种一对多的消息传递方式. 代理:是一种通用的设计模式,iOS中对代理支持的很好,由代理对象.委托者.协议三部分组成. block:iOS4.0中引入的一种回调方法,可以将回调处理代码直接写在block代码块中,看起来逻辑清晰代码整齐. target action:通过将对象传递到另一个类中,在另一个类中将该对象当做target的方式,来调用该对象方法,从

央视揭高价回收手机猫腻: 手机如何秒变“砖头”

6月22日消息,一部使用正常的手机,一到"拆机党"的手里,短短十几秒,就变成了无法开机的"砖头",只能超低价卖给对方,如果您也有过这样的经历,那么可能碰上骗子了. 沈阳市民小刘在今年3月份,到沈阳市东北通讯市场想把自己用了一个多月的手机卖掉,刚到地方,路边的摊贩说愿意高价回收他的手机.小刘来到柜台前,对方要求刷机检查,本以为检查完就可以拿钱走人了,可是接下来,让小刘意想不到的事情发生了. 受骗人小刘:他说我的手机进水了,又说ID是假的,登录不上去,就是完全报废的状态

iOS 代理反向传值

在上篇博客 iOS代理协议 中,侧重解析了委托代理协议的概念等,本文将侧重于它们在开发中的应用. 假如我们有一个需求如下:界面A上面有一个button.一个label.从界面A跳转到界面B,在界面B的输入框中输入字符串,在界面A的label上显示.这是一个典型的反向传值的例子.这个例子的核心是:"在界面B的输入框中输入字符串,在界面A的label上显示".也就是说:"界面B委托界面A显示字符串,页面A是界面B的代理".委托方向代理方反向传值. 那么我们该怎么用代理设

iOS 代理的具体使用

最近看了一个代理的使用文档,觉着写的很好,记录一下 1.     创建一个 delegate: 2.    委托者声明一个delegate: 3.    委托者调用delegate内的方法(method): 4.    被委托者设置delegate,以便被委托者调用: 5.    被委托者实现Delegate 所定义的方法. 1.1    第一步: 创建一个delegate 在 .h 文件中,  通过 @protocol 创建一个 delegate: @protocol CalculatorPr

IOS 代理的简单实现

原文 http://www.cnblogs.com/lovekarri/archive/2012/03/04/2379197.html 昨天做了一个demo,用到了简单代理. delegate是ios编程的一种设计模式.我们可以用这个设计模式来让单继承的objective-c类表现出它父类之外类的特征.昨天这个代理实现如下: 类GifView是继承自UIView的,它加载在RootViewController上来通过一个Timer播放动画.同时,RootViewController需要知道Tim