ReactiveSwift框架之Event源码分析
Event(事件)是ReactiveSwift的沟通的核心,它可以表示一次点击按钮,消息中心发送通知,数据状态改变,任务的完成,错误的发生等等,产生事件后通过Signal发送给任意数量的观察者(Observer)
具体源码列出来溜溜
extension Signal {
/// Represents a signal event.
///
/// Signals must conform to the grammar:
/// `value* (failed | completed | interrupted)?`
public enum Event {
case value(Value)
/// 表示Signal(信号)因为发生了错误(Error)而终止
case failed(Error)
/// 信号成功完成而终止
case completed
/// 由于取消cancel等原因而导致终止,表示该操作既不是成功也不是失败
case interrupted
}
...
}
从源码可以看出事件是一个枚举类型,它表示值 value
或者终止事件(failed
, completed
, interrupted
)之一,一旦终止就不会有后续事件再发送。
ReactiveSwift随着版本的更新迭代,已经将其放入Signal命名空间下了,这些变动明显变的更加合理,事件本就是Signal的发送单元,脱离了Signal也就变得没有意义了。还有一个变动就是将事件转换的代码定义成Event静态成员函数,老版本这些都在Signal里处理,放到Event里定义使得代码更加职责分明,从中我们也可以看出代码重构的艺术
接下来分析下事件转换操作,大家可能都用过数组的转换map函数来将一组数据转换为自己想要的,Event也提供了这些操作函数,代码如下
/*
代码很简单,功能就是将事件转换为其他类型的事件,如果事件是一个value事件,
就通过f闭包进行映射为新的事件
*/
public func map<U>(_ f: (Value) -> U) -> Signal<U, Error>.Event {
switch self {
case let .value(value):
return .value(f(value))
/// 可能有朋友在此疑问,为什么以下代码不直接简单的直接写成
/// default: return self, 答案是不能,因为转换后的事件签名是Siganl<U,Error>.Event,
/// 所以不能直接返回,源码中通过类型推断返回指定类型
case let .failed(error):
return .failed(error)
case .completed:
return .completed
case .interrupted:
return .interrupted
}
}
另一个转换映射的成员函数式mapError,跟map不同的事,它只转换failed事件,其他事件直接返回对应泛型事件,其他的分析和map一样。
/*
将产生的错误事件类型通过闭包f映射为其他的错误类型
*/
public func mapError<F>(_ f: (Error) -> F) -> Signal<Value, F>.Event {
switch self {
case let .value(value):
return .value(value)
case let .failed(error):
return .failed(f(error))
case .completed:
return .completed
case .interrupted:
return .interrupted
}
}
再来看看Event实现了哪些协议
extension Signal.Event where Value: Equatable, Error: Equatable {
public static func == (lhs: Signal<Value, Error>.Event, rhs: Signal<Value, Error>.Event) -> Bool
}
针对Value和Error都实现了Equatable协议时,条件扩展实现了相等比较,即两个Event可进行等同进行比较,顺便提一下
Equatable协议,从swift4.1开始针对enum,struct值类型遵循Equatable协议的如果成员变量实现了Equatable协议,会自动合成该实现方法,
不需要自己实现,但也有其限制,如果通过extention扩展或class遵循Equatable协议,就必须自己实现,
还有如果只针对部分成员变量来进行比较很显然合成的方法没法实现该需求。
extension Signal.Event: CustomStringConvertible
实现CustomStringConvertible协议很简单,只有一个var description:String 方法,该协议的作用就是能将对象
转为String,使用方法为let s = String(describing: p),通过print该对象时也会调用descripiton
说到这里已经差不多Event就完了,但还有一个比较难以理解的就是Event Transformations,以前的版本这些转换操作都是在Signal里的,暂时等到分析Signal源码时再分析