Swift Combine - задержка издателя - PullRequest
0 голосов
/ 05 апреля 2020

TL; DR

Я хочу отложить публикацию, но не могу понять, как объединить части

Вкратце

У меня есть Publisher

let generator = PassthroughSubject<Bool, Never>()

и я хочу как-нибудь использовать модификатор

.delay(for: 2, scheduler: RunLoop.main)

, чтобы при вызове

generator.send(true)

сообщение отправляется через две секунды после вызова 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)
        }
    }
}

1 Ответ

0 голосов
/ 06 апреля 2020

.delay(for: 2, scheduler: RunLoop.main), скорее всего, именно то, что вам нужно, но будет важно увидеть, как вы подписываетесь, чтобы полностью понять проблему. Задержка не задерживает отправку значения при использовании send() с темой - это ссылка на императивный код и отправляет данные всякий раз, когда вызывается send, как правило, для какой-то уже существующей подписки.

Хотя у вас есть подписчик в первом бите кода, нет ни одного, с которым можно связать их вместе.

Например, если вы обновили:

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

* От 1012 * до

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

Тогда оператор print должен сработать через ~ 2 секунды после вызова init (). В зависимости от того, что вы пытаетесь выполнить здесь sh, использование триггера закрытия, такого как onAppear, может сделать намного больше отправки, имея этот вызов subject.send(), который вы затем можете отложить как Вам нравится цепочка издателей, которая случается до того, как на нее подписывается.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...