4

我想创建一个重复功能,使用组合在我的代码中创建一个循环。我注意到,Combine 没有通过这个伟大的 repo 重复发布者: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
  })
4

2 回答 2

4

.retry(_:)运算符实际上旨在用于重试可能失败的操作,例如网络请求。听起来你需要一个计时器。幸运的是,从 Xcode 11 beta 2 开始,Apple 为TimerFoundation 中的类添加了 Publisher 支持。

关于您的实现的另一条评论:我假设此代码用于 a 中,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)
    }
}
于 2019-07-13T21:01:49.607 回答
3

你可以Timer.Publisher这样使用:

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

autconnect()Timer您在订阅后立即开始使用sink(_:).

于 2019-07-16T08:20:23.200 回答