Combine - 延迟发布者的发送
Combine - Delay publisher's send
什么是最好的方法来延迟发布者在 Swift Combine 中发送一些数据的时间?让我们假设以下情况:
private var publisher: PassthroughSubject<Progress, Error>
// closure called every second:
startWithProgress() { [weak self] progress in
self.publisher.send(.init(progress: progress))
// How to call this 0.5 second after the above `send`:
self.publisher.send(.init(progress: progress + 0.5))
}
我检查了 Delay
API,但似乎我需要创建另一个发布者才能使用它,这对我来说不是最佳选择。我还检查了 throttle
和 debounce
,但它们也不允许我一个接一个地发送 2 个更新,它们之间有给定的延迟。
看你分享的,我不会用Combine。 DispatchQueue.asyncAfter(deadline:execute:)
好像够了。
话虽这么说,但如果必须的话,可以使用 Publisher.delay(for:tolerance:scheduler:options:)
:
let subject = PassthroughSubject<Progress, Error>()
subject.delay(for: .seconds(5), scheduler: RunLoop.main)
.replaceError(with: .init())
.sink { progress in
self.publisher.send(.init(progress: progress + 0.5))
}
.store(in: &cancellables)
甚至Publisher.publish(every:tolerance:on:in:options:)
Timer
.publish(every: 5, on: .main, in: .default)
.autoconnect()
.first()
.sink { _ in
self.publisher.send(.init(progress: progress + 0.5))
}
或者,如果对您的情况有意义,在 @Published
变量中包含 progress
并使用它来启动管道
我还没有测试过,使用计时器可能更有意义。您需要将 cancelable 存储在一个实例变量中,这样它就不会在函数 returns.
时消失
var cancellable = self.publisher
.delay(for: .seconds(0.5), scheduler: RunLoop.main )
.sink(receiveCompletion:{ _ in
// do something with the error or completion
}, receiveValue:{ [unowned self] progress in
// you don't show any code that actually updates progress, without that this will just keep sending the initial value + 0.5.
self.publisher.send(.init(progress: progress + 0.5))
})
self.publisher.send(.init(progress: progress))
延迟发送值的行为(您可以使用 DispatchQueue.asyncAfter
执行)与创建延迟上游值的组合管道之间存在差异。
您没有详细说明您实际要完成的任务,因此很难给出明确的答案。
如果我概括地说,您似乎想要一个管道,它为每个上游值发出值,然后再次发出值 + 0.5
,但延迟。这可以像下面这样完成,例如:
let duplicateAndDelay = publisher
.flatMap { [([=10=], 0), ([=10=] + 0.5, 0.5)].publisher } // duplicate
.flatMap { (progress, delay) in
Just(progress)
.delay(for: .seconds(delay), scheduler: RunLoop.main) // delay
}
那么你可以 send
一次:
startWithProgress() { [weak self] progress in
self?.publisher.send(progress)
}
和return要订阅的duplicateAndDelay
发布者,而不是publisher
发布者。
什么是最好的方法来延迟发布者在 Swift Combine 中发送一些数据的时间?让我们假设以下情况:
private var publisher: PassthroughSubject<Progress, Error>
// closure called every second:
startWithProgress() { [weak self] progress in
self.publisher.send(.init(progress: progress))
// How to call this 0.5 second after the above `send`:
self.publisher.send(.init(progress: progress + 0.5))
}
我检查了 Delay
API,但似乎我需要创建另一个发布者才能使用它,这对我来说不是最佳选择。我还检查了 throttle
和 debounce
,但它们也不允许我一个接一个地发送 2 个更新,它们之间有给定的延迟。
看你分享的,我不会用Combine。 DispatchQueue.asyncAfter(deadline:execute:)
好像够了。
话虽这么说,但如果必须的话,可以使用 Publisher.delay(for:tolerance:scheduler:options:)
:
let subject = PassthroughSubject<Progress, Error>()
subject.delay(for: .seconds(5), scheduler: RunLoop.main)
.replaceError(with: .init())
.sink { progress in
self.publisher.send(.init(progress: progress + 0.5))
}
.store(in: &cancellables)
甚至Publisher.publish(every:tolerance:on:in:options:)
Timer
.publish(every: 5, on: .main, in: .default)
.autoconnect()
.first()
.sink { _ in
self.publisher.send(.init(progress: progress + 0.5))
}
或者,如果对您的情况有意义,在 @Published
变量中包含 progress
并使用它来启动管道
我还没有测试过,使用计时器可能更有意义。您需要将 cancelable 存储在一个实例变量中,这样它就不会在函数 returns.
时消失var cancellable = self.publisher
.delay(for: .seconds(0.5), scheduler: RunLoop.main )
.sink(receiveCompletion:{ _ in
// do something with the error or completion
}, receiveValue:{ [unowned self] progress in
// you don't show any code that actually updates progress, without that this will just keep sending the initial value + 0.5.
self.publisher.send(.init(progress: progress + 0.5))
})
self.publisher.send(.init(progress: progress))
延迟发送值的行为(您可以使用 DispatchQueue.asyncAfter
执行)与创建延迟上游值的组合管道之间存在差异。
您没有详细说明您实际要完成的任务,因此很难给出明确的答案。
如果我概括地说,您似乎想要一个管道,它为每个上游值发出值,然后再次发出值 + 0.5
,但延迟。这可以像下面这样完成,例如:
let duplicateAndDelay = publisher
.flatMap { [([=10=], 0), ([=10=] + 0.5, 0.5)].publisher } // duplicate
.flatMap { (progress, delay) in
Just(progress)
.delay(for: .seconds(delay), scheduler: RunLoop.main) // delay
}
那么你可以 send
一次:
startWithProgress() { [weak self] progress in
self?.publisher.send(progress)
}
和return要订阅的duplicateAndDelay
发布者,而不是publisher
发布者。