Swift Combine .repeat - PullRequest
       56

Swift Combine .repeat

1 голос
/ 12 июля 2019

Я хотел бы создать функцию повторения, которая создает цикл в моем коде с использованием Combine. Я заметил, что у Combine нет повторного издателя через этот великий репозиторий: https://github.com/freak4pc/rxswift-to-combine-cheatsheet. Вот код, который я написал, который работает, чтобы повторять 2 состояния. Как мне уменьшить это до чего-то более удобочитаемого или создать собственную функцию повтора?

toggleShouldDisplay = Just<Void>(())
  .delay(for: 2, scheduler:RunLoop.main)
  .map({ _ in
    self.shouldDisplay = true
    self.didChange.send(())
  })
  .delay(for: 2, scheduler: RunLoop.main)
  .map({ _ in
    self.shouldDisplay = false
    self.didChange.send(())
  })
  .setFailureType(to: NSError.self)
  .tryMap({ _ in
    throw NSError()
  })
  .retry(.max) // I might hit Int.max if I reduce the delays
  .sink(receiveValue: { _ in
    //Left empty
  })

Ответы [ 2 ]

0 голосов
/ 16 июля 2019

Вы можете использовать Timer.Publisher следующим образом:

toggleShouldDisplay = Timer.publisher(every: 2, on: .main, in: .default)
  .autoconnect()
  .sink {
    self.shouldDisplay = !self.shouldDisplay
    self.didChange.send(())
  }

autconnect() позволяет начать Timer, как только вы подпишетесь, используя sink(_:).

0 голосов
/ 14 июля 2019

Оператор .retry(_:) действительно предназначен для повторных попыток, которые могут привести к сбою, например сетевых запросов.Похоже, вам нужен таймер вместо этого.К счастью, начиная с Xcode 11 beta 2, Apple добавила поддержку Publisher в класс Timer в Foundation.

Еще один комментарий о вашей реализации: я предполагаю, что этот код используется в BindableObject, потому что выдоступ didChange.Поскольку didChange может быть любого типа Publisher, почему бы не использовать ваше свойство shouldDisplay в качестве Publisher?

final class MyModel: BindableObject {
    var didChange: CurrentValueSubject<Bool, Never> { shouldDisplaySubject }
    var shouldDisplay: Bool { shouldDisplaySubject.value }

    private let shouldDisplaySubject = CurrentValueSubject<Bool, Never>(false)
    private var cancellables: Set<AnyCancellable> = []

    init() {
        startTimer()
    }

    private func startTimer() {
        Timer.publish(every: 2, on: .main, in: .default)
            .autoconnect()
            .scan(false) { shouldDisplay, _ in
                !shouldDisplay
            }
            .assign(to: \.value, on: shouldDisplaySubject)
            .store(in: &cancellables)
    }
}
...