Swift Combine - 延迟发布者

And*_*can 2 delay publish-subscribe combine

TL; 博士

我想推迟发表,但不知道如何,呃,把这些部分结合起来

简单来说

我有一个 Publisher

let generator = PassthroughSubject<Bool, Never>()
Run Code Online (Sandbox Code Playgroud)

并想以某种方式使用修饰符

.delay(for: 2, scheduler: RunLoop.main)
Run Code Online (Sandbox Code Playgroud)

所以当我打电话

generator.send(true)
Run Code Online (Sandbox Code Playgroud)

消息在呼叫后两秒发送 send()

查看文档Publishers.Delay使类型错误更加清晰,但并不能帮助我找到正确的连接方式。

代码

import SwiftUI
import Combine

// Exists just to subscribe.
struct ContainedView : View {
    private let publisher: AnyPublisher<Bool, Never>
    init(_ publisher: AnyPublisher<Bool, Never> = Just(false).dropFirst().eraseToAnyPublisher()) {
        self.publisher = publisher
    }
    var body: some View {
        Rectangle().onReceive(publisher) { _ in print("Got it") }
    }
}

struct ContentView: View {
    let generator = PassthroughSubject<Bool, Never>()
                 // .delay(for: 2, scheduler: RunLoop.main)
                 // Putting it here doesn't work either.

    var body: some View {
        VStack {
            Button("Tap") {

                // Does not compile
                self.generator.delay(for: 2, scheduler: RunLoop.main).send(true)
                // Value of type 'Publishers.Delay<PassthroughSubject<Bool, Never>, RunLoop>' has no member 'send'
                // https://developer.apple.com/documentation/combine/publishers/delay

                // Does not compile
                self.generator.send(true).delay(for: 2, scheduler: RunLoop.main)
                // Value of tuple type '()' has no member 'delay'

                // Just a broken-up version of the first try.
                let delayed = self.generator.delay(for: 2, scheduler: RunLoop.main)
                delayed.send(true)

                // This, of course, builds and works.
                self.generator.send(true)
                print("Sent it")
            }

            ContainedView(generator.eraseToAnyPublisher())
            .frame(width: 300, height: 200)
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

小智 7

您可以使用发布者的 debounce 属性来延迟发布。

$yourProperty
    .debounce(for: 0.8, scheduler: RunLoop.main)
    .eraseToAnyPublisher()
Run Code Online (Sandbox Code Playgroud)


hec*_*ckj 6

.delay(for: 2, scheduler: RunLoop.main)可能正是您所需要的,但关键是要了解您如何订阅以完全了解问题。send()与主题一起使用时,延迟不会延迟值的发送- 这是命令式代码的链接,并在send调用时发送数据,通常针对某些已经存在的订阅。

虽然您在代码的第一位中有一个订阅者,但没有一个主题可以将它们固定在一起。

例如,如果您更新:

Just(false).dropFirst().eraseToAnyPublisher()

Just(false).dropFirst().eraseToAnyPublisher().delay(for: 2, scheduler: RunLoop.main)

然后打印语句应该在调用 init() 后约 2 秒触发。根据您在此处尝试完成的工作,使用闭包触发器(例如onAppear可能会发送更多),调用subject.send(),然后您可以根据需要在发布者链中延迟任何订阅它之前发生的事情。