3

我已经使用 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真正必要的。

提前致谢。

4

1 回答 1

6

您是正确的,您不需要保留结果startWithResult以保持订阅有效。文档的相关部分说

必须公开保留ASignal以附加新的观察者,但不一定要保持事件流活着。此外,Signal只要还有一个活跃的观察者,a 就会保留自己。

因此,只要您不处置从 中返回的对象startWithResult,即使您不保留它,操作也会继续。

相反,Lifetime是关于取消操作。在这种情况下,因为您附加了startWithResultto的生命周期的结果,所以当对象被释放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)
            }
    }
}
于 2018-11-29T18:46:20.307 回答