就我自己感觉而言,使用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
- 准备一些需要用但是没有的方法
// 这四个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)
}
- 创建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
}
- 扩展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这样的链式调用,既可以保持代码的统一性,又可以当做中间层,隔离第三方。