美文网首页
代理支持rxSwift

代理支持rxSwift

作者: __ENUUI | 来源:发表于2017-08-01 22:53 被阅读0次

    就我自己感觉而言,使用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

    相关文章

      网友评论

          本文标题:代理支持rxSwift

          本文链接:https://www.haomeiwen.com/subject/avijlxtx.html