我已经使用ReactiveSwift几个月了,但有一点我还不完全理解:终身对象。
例如,假设我有一个SignalProducer
,它将进行API调用,这被包装在一个类上:
class ServiceWrapped {
private let service: Service // the method called on this object returns the SignalProducer
private let (lifetime, token) = Lifetime.make()
// more stuff
func fetchSomething(completion: @escaping (Value?, Error?) -> Void) {
lifetime += service.fetchSomething()
.startWithResult { result in
switch result {
case .success(let value):
completion(value, nil)
case .failure(let error):
completion(nil, error)
}
}
}
}
我的问题是:在这种情况下有必要使用lifetime
吗?
我知道lifetime
将保留服务调用,所以当它返回时它会有一些东西,但由于它也封装在ServiceWrapped
上,我认为使用lifetime
真的没有必要。
提前谢谢。
您没有必要为了保持订阅的有效性而保留startWithResult
的结果,这是正确的。文件的相关部分写道:
Signal
必须公开保留,以便附加新的观察者,但不一定是为了保持事件流的活动性。此外,只要仍然存在活跃的观察者,Signal
就保持其自身。
因此,只要您不处理从startWithResult
返回的对象,即使您不保留它,操作也会继续。
相反,Lifetime
是关于取消操作。在这种情况下,因为您已将startWithResult
的结果附加到ServiceWrapped
的生存期,所以当释放ServiceWrapped
对象时,该操作将被取消。如果省略lifetime +=
,则即使解除分配ServiceWrapped
,操作也将继续。
如果您有一个从web加载图像的视图控制器,那么这就是为什么有用的一个实际例子。如果用户在图像加载完成之前关闭了视图控制器,那么您可能想要取消web请求。您可以通过将图像加载生成器与视图控制器的生存期绑定来实现这一点。这不是为了保持网络请求的有效性,而是在不再需要时取消它。
撇开风格不谈,文档建议您使用运算符,而不是处理startWithResult
:的结果
func fetchSomething(completion: @escaping (Value?, Error?) -> Void) {
service.fetchSomething()
.take(during: lifetime)
.startWithResult { result in
switch result {
case .success(let value):
completion(value, nil)
case .failure(let error):
completion(nil, error)
}
}
}