SignalProducer
SignalProducer是ReactiveSwift中冷信号的实现, 是第二种发送事件的途径.
热信号是活动着的事件发生器, 相对应的, 冷信号则是休眠中的事件发生器. 也就是说冷信号需要一个唤醒操作, 然后才能发送事件, 而这个唤醒操作就是订阅它. 因为订阅后才发送事件, 显然, 冷信号不存在时机早晚的问题. 仍以春晚举例:
冷信号相当于春晚的视频文件而不是现场直播, 正常情况下, 视频文件肯定是不会自动播放的, 但你只要一双击, 它就被启动播放然后输出节目了.
//1. 通过SignalProducer.init(startHandler: (Observer, Lifetime) -> Void)创建SignalProducer
let producer = SignalProducer { (innerObserver, lifetime) in
lifetime.observeEnded({
print("信号无效了 你可以在这里进行一些清理工作")
})
//2. 向外界发送事件
innerObserver.send(value: 1)
innerObserver.send(value: 2)
innerObserver.sendCompleted()
}
//3. 创建一个观察者封装事件处理逻辑
let outerObserver = Signal.Observer(value: { (value) in
print("did received value: (value)")
})
//4. 添加观察者到SignalProducer
producer.start(outerObserver)
输出: did received value: 1
did received value: 2
信号无效了 你可以在这里进行一些清理工作
typealias Producer = ReactiveSwift.SignalProducer
let producer = Producer { (innerObserver, _) in
//没什么想清理的
innerObserver.send(value: 1)
innerObserver.send(value: 2)
innerObserver.sendCompleted()
}
producer.startWithValues { (value) in
print("did received value: (value)")
}
producer.startWithFailed(action: )
producer.startWithResult(action: )
producer.startWithXXX...各种便利函数
和Signal的订阅方式如出一辙, 只是名字换了一下, Signal.observeXXX换成了SignalProducer.startXXX.
都是事件发生器, 所以API方面Signal和SignalProducer都是一样的,上面的map, on, merge, comblinelast...等等, SignalProducer也有一份, 作用也都一样, 我就不多说了, 这里简单给两段代码说说可能遇到的坑
func fetchData(completionHandler: (Int, Error?) -> ()) {
print("发起网络请求")
completionHandler(1, nil)
}
let producer = Producer {[unowned self] (innerObserver, _) in
self.fetchData(completionHandler: { (data, error) in
innerObserver.send(value: data)
innerObserver.sendCompleted()
})
}
producer.startWithValues { (value) in
print("did received value: (value)")
}
producer.startWithValues { (value) in
print("did received value: (value)")
}
输出: 发起网络请求
did received value: 1
发起网络请求
did received value: 1
也许你只是想两个观察者共享一次网络请求带回的Event, 但事实上这里会发生两次网络请求, 但这不是一个bug, 这是一个feature.
SignalProducer的一个特性是, 每次被订阅就会执行一次初始化时保存的闭包.
所以如果你有类似一次执行, 多处订阅的需求, 你应该选择Signal而不是SignalProducer. 所以, 符合需求的代码可能是这样:
let signalTuple = NSignal.pipe()
signalTuple.output.observeValues { (value) in
print("did received value: (value)")
}
signalTuple.output.observeValues { (value) in
print("did received value: (value)")
}
self.fetchData { (data, error) in
signalTuple.input.send(value: data)
signalTuple.input.sendCompleted()
}
输出: 发起网络请求
did received value: 1
did received value: 1
到目前为止, 示例代码中给到的都是NoError类型的信号, 在实际开发中, 这显然是不可能的, 毕竟错误是不可避免的. 通常我们的项目会声明一个类似APIError的错误类型来表示这些错误, 所以你可能会有这样的声明:
structAPIError: Swift.Error {
let code: Int
var reason =""
}
typealias NSignal = ReactiveSwift.Signaltypealias
APISignal = ReactiveSwift.Signaltypealias
Producer = ReactiveSwift.SignalProducertypealias
APIProducer = ReactiveSwift.SignalProducer
这样的声明很好, 能让ReactiveSwift写起来像RXSwift一样"简洁". 但这里需要加上下面的代码才能更好的工作:
extension SignalProducer where Error == APIError {
@discardableResult
func startWithValues(_ action: @escaping (Value) -> Void) -> Disposable {
returnstart(Signal.Observer(value: action))
}
}
这是因为默认的SignalProducer是没有startWithValues函数的, ReactiveSwift会在Extension里给它加上startWithValues函数, 但是这只对NoError有效, 所以当你在自定义Error时, 请记得加上类似的代码.
网友评论
还是viewModel.responseSuccess.signal.observeValues { [unowned self](success) in}
要不要弱引用self. 弱引用self 会Crash