Я бы хотел, чтобы все издатели выполняли, если явно не отменены. Я не возражаю против того, чтобы AnyCancellable
выходил из области видимости, однако, основываясь на документах, он автоматически вызывает cancel
на deinit
, что нежелательно.
Я пытался использовать сумку с возможностью отмены, но AnyCancelable
продолжал накапливаться даже после того, как издатель уволил завершение.
Должен ли я управлять сумкой вручную? У меня сложилось впечатление, что store(in: inout Set)
должен был быть использован для удобства управления отменяемыми экземплярами, однако все, что он делает, это толкает AnyCancellable
в набор.
var cancelableSet = Set<AnyCancellable>()
func work(value: Int) -> AnyCancellable {
return Just(value)
.delay(for: .seconds(1), scheduler: DispatchQueue.global(qos: .default))
.map { $0 + 1 }
.sink(receiveValue: { (value) in
print("Got value: \(value)")
})
}
work(value: 1337).store(in: &cancelableSet)
DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(5)) {
print("\(cancelableSet)")
}
То, что я до сих пор придумал,который отлично работает, но заставляет задуматься, что-то отсутствует в платформе Combine или не предназначено для такого использования:
class DisposeBag {
private let lock = NSLock()
private var cancellableSet = Set<AnyCancellable>()
func store(_ cancellable: AnyCancellable) {
print("Store cancellable: \(cancellable)")
lock.lock()
cancellableSet.insert(cancellable)
lock.unlock()
}
func drop(_ cancellable: AnyCancellable) {
print("Drop cancellable: \(cancellable)")
lock.lock()
cancellableSet.remove(cancellable)
lock.unlock()
}
}
extension Publisher {
@discardableResult func autoDisposableSink(disposeBag: DisposeBag, receiveCompletion: @escaping ((Subscribers.Completion<Self.Failure>) -> Void), receiveValue: @escaping ((Self.Output) -> Void)) -> AnyCancellable {
var sharedCancellable: AnyCancellable?
let disposeSubscriber = {
if let sharedCancellable = sharedCancellable {
disposeBag.drop(sharedCancellable)
}
}
let cancellable = self.handleEvents(receiveCompletion: { _ in
disposeSubscriber()
}, receiveCancel: {
disposeSubscriber()
}).sink(receiveCompletion: receiveCompletion, receiveValue: receiveValue)
sharedCancellable = cancellable
disposeBag.store(cancellable)
return cancellable
}
}