如何使用 ReactiveCocoa 制作互斥信号

how to make mutex signals with ReactiveCocoa

我有一个视图控制器,它有两个信号。一种是下拉刷新信号,另一种是上拉加载更多信号。常见的场景有两种:

  1. 如果下拉信号是运行,新的下拉信号和上拉信号应该不会触发。
  2. 如果上拉信号是运行,新的上拉信号和下拉信号应该不会触发。

参考文档,发现switchToLatest算子可以同时禁止同一个信号运行。然而它并不完美,因为 switchToLatest 是在旧信号未完成时启动一个新信号,并将新信号的下一个发送给订阅者。我想要的是,如果信号是 运行,则不应触发新信号。

在没有RAC的世界里,我必须保持一个isLoading状态;在触发下拉或上拉信号之前,我会检查 isLoading 并确定应该触发信号。

RAC 世界有没有什么优雅的方法可以去除 isLoading 状态?

一般情况下你需要在信号中发送这些状态变化。

尝试使用 RACSubject 来更改每个单独进程的状态(上拉和下拉)。他们每个人都应该订阅相反的和自己的 RACSubject 信号,并且在新的触发调用期间应用以下运算符:

- (RACSignal *)combineLatestWith:(RACSignal *)signal;

像这样:

RACSubject *pullUpStateChanged = [RACSubject subject];
RACSubject *pullDownStateChanged = [RACSubject subject];

RACSignal *stateChangeTrigger = [pullUpStateChanged combineLatestWith:pullDownStateChanged]
[stateChangeTrigger
  filter:^BOOL(RACTuple *tuple) {
      /// second item should contains tuple with 2 states
      /// based on this value you can reject some of the flows

  }] 
 flattenMap:^RACStream *(id value) {

}];

注意: combineLatestWith: 将在每个信号至少触发一次时开始工作。这就是发送初始状态 @NO(或其他值)的原因。否则,您可以改用真正的触发器。

P.S. 我没有在 Xcode.

中验证和构建提供的代码

更新: 所有你需要通过 sendNext: 在适当的 RACSubject 上将 pullUp 和 pullDown RACSignal's 数据转发给受试者。在这里使用主题有点开销,但您需要在两个信号都已触发的状态之前开始工作(不幸的是,如果两个信号都没有准备好,则不会触发)。这就是为什么您需要使用 RACSubjects 作为真实触发器和实际操作之间的中介。

UPDATE2: 实际上这是一个有趣的挑战,我已经尝试实现这种事情。我遇到了一个问题。在使用 combineLatestWith: 时,您将被迫不仅从实际触发器获取更新,而且还从相反的触发器获取更新。并且您需要用一些 ID 来区分更改请求。我已经放置了完整的实现 here