使用combineLatest,有没有办法找出事件发出的信号?

时间:2016-01-05 12:47:44

标签: objective-c reactive-cocoa

正如标题所述,有一种方法可以执行以下操作:

[[RACSignal combineLatest:@[signal1, signal2]] subscribNext:^id(RACTuple *signals) {
    // Did signal1 or signal2 emit an event?
}];

因此,在subscribeNext块中,我目前还不知道发出了哪个信号。

我试图解决的问题是涉及为选择器生成信号的问题(使用rac_signalForSelector),并且我希望在触发这些方法中的任何一个时得到通知。我想将事件合并在一起,但除了实际调用的方法之外,我不想要其中任何一个的最新值。

e.g。

RACSignal *signal1 = [self rac_signalForSelector@selector(method1:)];
RACSignal *signal2 = [self rac_signalForSelector@selector(method2:)];

[[RACSignal combineLatest:@[signal1, signal2]] subscribNext:^id(RACTuple *signals) {
    // Did signal1 or signal2 emit an event?
}];

2 个答案:

答案 0 :(得分:1)

假设您示例中的signal1signal2发送了相同类型的值,并且您希望对每个信号的值执行相同操作,则可以使用merge:而不是combineLatest:只是获取每个触发的值的信号:

[[RACSignal merge:@[signal1, signal2]] subscribeNext:^(NSObject *latestValue) {
    NSLog(@"%@", latestValue);
}];

如果您想以不同方式对待它们,则根本不需要使用combineLatest:merge: - 您可以单独订阅每个。

请注意,merge:combineLatest:之间的一个区别在于,merge:,只要调用第一个方法,就会调用您的块 - 它不会等到每个方法在开始触发之前至少调用一次,如combineLatest:那样。如果需要这种行为,可以使用then:运算符来实现。

如果,不仅需要知道“最近调用”方法的参数,而且上次使用其他方法的参数调用,你需要等到每个方法至少被调用一次...你可以做的一件事是将每个信号映射到(id whateverTheyActuallySent, NSUInteger sharedMonotonicallyIncreasingIdentifier)的元组,然后组合那些信号,然后根据该标识符对它们进行排序。

这将是......不优雅,但只有非常奇怪的情况才能保证这一点,如果你确实认为这是最好的方法,那么缩小一个级别以查看是否有其他东西可以改变以便更好毕竟你不必这样做。

答案 1 :(得分:1)

正如伊恩在回答中提到的,你可能想要使用merge代替combineLatest

由于您不关心rac_signalForSelector中的值,因此您可以使用mapReplace运算符来区分method1method2

  RACSignal *signal1 = [[self rac_signalForSelector:@selector(method1:)] mapReplace:@YES];
  RACSignal *signal2 = [[self rac_signalForSelector:@selector(method2:)] mapReplace:@NO];

  [[RACSignal merge:@[signal1, signal2]] subscribeNext:^(NSNumber *latestValue) {
    if(latestValue.boolValue) {
      //first method was called
    }
  }];

我发现这种方法对于处理“对立”事件很有用,例如rac_signalForControlEvents参数UIControlEventTouchDownInsideUIControlEventTouchUpInside