ReactiveSwift 的终生目标

Lifetime purpose on ReactiveSwift

我已经使用 ReactiveSwift 几个月了,但有一点我还没有完全理解:生命周期对象。

例如,假设我有一个 SignalProducer 将进行 API 调用,它被包裹在 class:

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 会保留服务调用,所以它在 return 时有一些东西,但因为它也包含在 ServiceWrapped 上,所以我不认为使用 lifetime真的很有必要。

提前致谢。

你是对的,你不需要保留 startWithResult 的结果来保持订阅有效。 relevant part of the documentation says:

A Signal must be publicly retained for attaching new observers, but not necessarily for keeping the stream of events alive. Moreover, a Signal retains itself as long as there is still an active observer.

所以只要你不处理从 startWithResult 返回的对象,即使你不保留它,操作也会继续。

相反,Lifetime 是关于取消 操作。在这种情况下,因为您已将 startWithResult 的结果附加到 ServiceWrapped 的生命周期,所以当 ServiceWrapped 对象被释放时,操作将被取消。如果您省略 lifetime +=,那么即使 ServiceWrapped 被释放,操作也会继续。

如果您有一个从 Web 加载图像的视图控制器,那么这个功能为何有用的一个实际示例就是。如果用户在图像加载完成之前关闭了视图控制器,那么您可能想要取消 Web 请求。您可以通过将图像加载生成器绑定到视图控制器的生命周期来做到这一点。这不是让网络请求保持活动状态,而是在不再需要时取消它。

关于风格,documentation recommends you use operators rather than handling the result of the 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)
            }
    }
}