代理支持rxSwift

就我自己感觉而言,使用Swift在书写上更加简洁、便于扩展、和oc桥接也很简单。而且Swift已经是第三个大版本了,今年的开发者大会也基本没有提swift的事,说明Swift已经相当稳定了。Swift的发展趋势也不错,普及应该是早晚的事。
在Swift社区,rxSwift是一个相当有影响力,且值得一用的Api。各个社区关于rxSwift的教程也有很多,它本身的文档也非常详细。
本文主要分享一下我自己的使用过程中感觉非常有趣的一个小tip: 自定义的代理手动支持rxSwift。

集成:
pod 直接集成就可以。(�我觉得考虑这么做的前提是项目中正在使用rxSwift。不然,真没必要)

    pod 'RxSwift'
    pod 'RxCocoa'

一、 准备好要搞的代理,只是一个demo,所以代码是毫无营养的

@objc protocol DemoDelegate: NSObjectProtocol {
    @objc optional func demo(d: Demo, didSetName name: String)
}

class Demo: NSObject {
    weak public var delegate: DemoDelegate?
    
    public var name: String? {
        didSet {
            if let n = name {
                self.delegate?.demo?(d: self, didSetName: n)
            }
        }
    }
}

二、 准备工作
创建一个单独的文件,如果是第三方的代理就引入代理所在的头文件,如果是项目里的就不用了。下面两个头文件还是要引入的。

import RxCocoa
import RxSwift
  1. 准备一些需要用但是没有的方法
// 这四个func 是rxSwift的错误处理方法,没有用public修饰,无法直接使用,拷贝当前文件就可以用啦。
func castOrThrow<T>(_ resultType: T.Type, _ object: Any) throws -> T {
    guard let returnValue = object as? T else {
        throw RxCocoaError.castingError(object: object, targetType: resultType)
    }
    
    return returnValue
}

func castOptionalOrFatalError<T>(_ value: Any?) -> T? {
    if value == nil {
        return nil
    }
    let v: T = castOrFatalError(value)
    return v
}

func castOrFatalError<T>(_ value: Any!) -> T {
    let maybeResult: T? = value as? T
    guard let result = maybeResult else {
        rxFatalError("Failure converting from &&\(value)&& to \(T.self)")
    }
    return result
}

func rxFatalError(_ lastMessage: String) -> Never  {
    fatalError(lastMessage)
}
  1. 创建RxDelegateDemoDelegateProxy类继承自RxCocoa.DelegateProxy,并遵守DelegateProxyType协议以及目标代理DemoDelegate
    <1> override父类方法
override public class func createProxyForObject(_ object: AnyObject) -> AnyObject {
        let p: Demo = castOrFatalError(object)
        return p.createRxDelegateProxy()
    }

<2> 实现DelegateProxyType中代理的set和get方法

public class func setCurrentDelegate(_ delegate: AnyObject?, toObject object: AnyObject) {
        let p: Demo = castOrFatalError(object)
        p.delegate = castOptionalOrFatalError(delegate)
    }
public class func currentDelegateFor(_ object: AnyObject) -> AnyObject? {
        let p: Demo = castOrFatalError(object)
        return p.delegate
    }
  1. 扩展Demo类
extension Demo {
    public func createRxDelegateProxy() -> RxDelegateDemoDelegateProxy {
        return RxDelegateDemoDelegateProxy(parentObject: self)
    }
}

三、 准备就绪,扩展rxSwift的Reactive,这是一个结构体。

extension Reactive where Base: Demo {
    //  实现这个,创建的类(本文是Demo)类的对象就可以点出rx了
    var delegate: DelegateProxy {
        return RxDelegateDemoDelegateProxy.proxyForObject(base)
    }
   //  ControlEvent<>的尖括号里可以是单个类型,也可以是组元。组元用于监听多个参数。
    var didSetName: ControlEvent<String> {
       /**
          DelegateProxy的对象方法 methodInvoked 。
          点到这个方法里,有一大坨的注释解释这个方法。
          大概的意思是说methodInvoked方法只能监听返回值是Void的代理方法。
          有返回值的代理方法要用PublishSubject这个监听,还给了个例子,有兴趣可以点进去看一下。
        */
        let source = delegate.methodInvoked(#selector(DemoDelegate.demo(d:didSetName:))).map({ (a:[Any]) -> String in
            // map函数可以接收到代理方法的参数。可以是单个参数,也可以是多个参数。根据需要取值就可以了,根据参数在代理方法中的位置,下标从0开始。本文实现中,只需要第二个参数,数以取1.
            let i = try castOrThrow(String.self, a[1])
            return i
        })
        //  创建event返回
        return ControlEvent(events: source)
    }
}

到此为止,自定义的代理也可以使用rxSwift监听了。当然在实际Swift中这样的感觉多写了不少。而且很多数据、事件的传递用闭包就轻松搞定了。
但是,也可以用同样的方法让第三方中的代理支持rxSwift这样的链式调用,既可以保持代码的统一性,又可以当做中间层,隔离第三方。

源码:RxSwiftTipDemo

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,271评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,275评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,151评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,550评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,553评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,559评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,924评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,580评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,826评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,578评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,661评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,363评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,940评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,926评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,156评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,872评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,391评论 2 342

推荐阅读更多精彩内容

  • 发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注 2017.06.26 09:4...
    肇东周阅读 12,016评论 4 62
  • 在我们的生活中,很多的地方都出现过吉他这种乐器,可是虽然这种乐器很酷,可是在背后的努力,那真是很苦啊 ...
    期待待续阅读 180评论 0 1
  • 严如斯每一天和来酒吧消遣的各色人等打交道,对各种突发事件都处理的游刃有余。这本领的练就需要的不止是忍气吞声,低眉顺...
    樵砥阅读 237评论 2 1
  • 到了一个陌生的村庄,一个刚毕业的大学生该干些什么? 没错,熟悉村中的情况。一家家走访,逮着谁就问。村里人遇到一个陌...
    毛线兄阅读 95评论 0 0