让\xe2\x80\x99s 假设您正在 AnyCancellable 上使用内置.store(in:)
方法,如下所示:
private var subscriptions = Set<AnyCancellable>()\n\nlet newPhotos = photos.selectedPhotos\nnewPhotos\n .map { [unowned self] newImage in\n return self.images.value + [newImage]\n }\n .assign(to: \\.value, on: images)\n .store(in: &subscriptions)\n
Run Code Online (Sandbox Code Playgroud)\n如果您有一个经常执行此操作的应用程序 - 发布商完成后这些内容是否会被删除?
\n另外,如果我决定采用这种方法:
\nprivate var newPhotosSubscription: AnyCancellable?\n\nself.newPhotosSubscription = newPhotos\n .map { [unowned self] newImage in\n self.images.value + [newImage]\n }\n .assign(to: \\.value, on: images)\n
Run Code Online (Sandbox Code Playgroud)\n每次我再次调用该方法时,它都会覆盖 AnyCancellable,前一个会发生什么?它在被释放之前是否仍然完成?
\nD\xc3\xa1vid P\xc3\xa1sztor 的解决方案很接近,但它有一个竞争条件。具体来说,假设发布者在方法返回之前newPhotos
同步完成。有些出版商就是这样运作的。两者都是如此。sink
Just
Result.Publisher
在这种情况下,完成块会在sink
返回之前运行。然后,sink
返回AnyCancellable
存储在 中的一个newPhotosSubscription
。但订阅已经完成,因此newPhotosSubscription
永远不会被设置回零。
例如,如果您URLSession.DataTaskPublisher
在实时代码中使用 a 但替换为Just
在某些测试用例中替换了发布者,则测试可能会触发竞争条件。
解决此问题的一种方法是:跟踪订阅是否已完成。sink
返回后、设置前检查一下newPhotosSubscription
。
private var ticket: AnyCancellable? = nil\n\nif ticket == nil {\n var didComplete = false\n let newTicket = newPhotos\n .sink(\n receiveValue: { [weak self] in\n self?.images.value.append($0)\n },\n receiveCompletion: { [weak self] _ in\n didComplete = true\n self?.ticket = nil\n }\n )\n if !didComplete {\n ticket = newTicket\n }\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n\n每次我再次调用该方法时,它都会覆盖 AnyCancellable,前一个会发生什么?它在被释放之前是否仍然完成?
\n
前一个(如果有)被取消,因为对旧的唯一引用AnyCancellable
被销毁,因此 被AnyCancellable
销毁。当 anAnyCancellable
被销毁时,它会自行取消(如果尚未取消)。
归档时间: |
|
查看次数: |
6935 次 |
最近记录: |