如何使用ReactiveCocoa制作互斥信号

时间:2015-10-13 15:22:30

标签: reactive-cocoa

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

  1. 如果下拉信号正在运行,则不应触发新的下拉信号和上拉信号。
  2. 如果上拉信号正在运行,则不应触发新的上推信号和下拉信号。
  3. 参考文档,我发现switchToLatest运算符可以禁止同时运行相同的信号。然而,它并不完美,因为当旧信号未完成时,switchToLatest将启动一个新信号,并将新信号发送到用户旁边。我想要的是如果信号正在运行,新信号不应该触发。

    在无RAC世界中,我必须维持一个isLoading状态;在触发下拉或上拉信号之前,我将检查isLoading并确定应触发信号。

    在RAC世界中是否有任何优雅的方法来移除isLoading状态?

1 个答案:

答案 0 :(得分:1)

通常,您需要在信号中发送这些状态更改。

尝试使用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中验证和构建提供的代码。

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

UPDATE2:实际上这是一项有趣的挑战,我试图实施这类工作。我遇到过一个问题。在使用combineLatestWith的同时:你不仅要从实际触发器获得更新,而且还要相反。而且您需要区分具有某些ID的更改请求。我已完全实施here