这是在完成对项目3.0升级之后,SnapKit
和ReactiveCocoa
框架使用方式变化,让我好奇的去阅读了一下框架的源码。学到了这个优雅的写法,觉得很受用。
在swift3.0之前,snapKit
和ReactiveCocoa
的用法是这样的:
view.snp_makeConstraints { (make) in
view.snp_top.equalTo(self)
}
let searchStrings = textField.rac_textSignal()
.toSignalProducer()
.map { text in text as! String }
到了swift3.0,两边的使用方式变成这样:
view.snp.makeConstraints { (make) -> Void in
view.snp.top.equalTo(self)
}
let searchStrings = textField.reactive.textValues
可以看出Swift3.0之后,框架不再是直接给对应的类扩展方法,而是同意给所有类扩展一个属性,然后,通过该属性扩展方法。
具体的是怎么实现的呢,翻看ReactiveCocoa
的源码找到了实现方式,在这里做总结:
1.定义一个协议 ReactiveExtensionsProvider
2.定义一个带泛型类型的结构体Reactive<Base>
,该结构体有一个 泛型类型的成员变量,初始化方法,需要传一个泛型类型的实例。
3.给协议添加一个Reactive<Base>
类型的只读属性:reactive
,把调用该写的对象self
作为初始化方法参数
4.让NSObject
遵守ReactiveExtensionsProvider
,就相当于NSObject
和他的所有子类都遵守了该协议,也就有了 reactive
属性
5.给Reactive
写Extension
用 where
判断Base
类型,不同的类型写不同的方法
以下是我自己写的一段Demo代码
import UIKit
//定义一个协议
protocol ProviderProtocol {}
//扩展协议
extension ProviderProtocol{
public var provider: Provider<Self> {
return Provider(self)
}
}
//定义一个结构体
struct Provider<CurrentClass> {
public let currentInstance: CurrentClass
fileprivate init(_ currentInstance: CurrentClass) {
self.currentInstance = currentInstance
}
}
//让所有的类都遵守协议
extension NSObject: ProviderProtocol {}
//给不同的类实现不同的方法
extension Provider where CurrentClass: UILabel{
func getTextCharacterCount() -> Int{
return currentInstance.text?.characters.count ?? 0
}
}