使用 combineLatest,有没有办法找出哪个信号发出了事件?
Using combineLatest, is there a way to find out which signal emitted the event?
如标题所述,有没有办法执行以下操作:
[[RACSignal combineLatest:@[signal1, signal2]] subscribNext:^id(RACTuple *signals) {
// Did signal1 or signal2 emit an event?
}];
所以在 subscribeNext 块中,我目前不知道触发了哪个信号。
我试图解决的问题涉及为选择器生成信号(使用 rac_signalForSelector),我希望在这些方法中的任何一种被触发时得到通知。我想将事件合并在一起,但除了实际调用的方法之外,我不想要任何事件的最新值。
例如
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?
}];
假设您示例中的 signal1
和 signal2
正在发送相同类型的值,并且您想对每个信号的值执行相同的操作,您可以使用 merge:
而不是 combineLatest:
以获得每个触发的值的信号:
[[RACSignal merge:@[signal1, signal2]] subscribeNext:^(NSObject *latestValue) {
NSLog(@"%@", latestValue);
}];
如果您想区别对待它们,则根本不需要使用 combineLatest:
或 merge:
-- 您可以单独订阅每一个。
请注意 merge:
和 combineLatest:
之间的一个区别是,对于 merge:
,您的块将在第一个方法被调用时立即被调用——它不会等到每个方法在开始触发之前至少被调用一次,就像 combineLatest:
那样。如果需要这种行为,可以使用 then:
运算符来实现。
如果您做不仅需要知道"most recently invoked"方法的参数而且还参数从上次调用其他方法开始,您确实需要等到每个方法至少被调用一次……您可以做的一件事是将每个信号映射到 (id whateverTheyActuallySent, NSUInteger sharedMonotonicallyIncreasingIdentifier)
的元组中,然后组合 那些信号,然后根据该标识符对它们进行排序。
这将是...不雅观,但只有在非常奇怪的情况下才能保证这样做,如果您确实认为这是最好的方法,那么最好再缩小一个级别,看看是否可以更改其他内容这样您就不必这样做了。
正如 Ian 在他的回答中提到的,您可能想使用 merge
而不是 combineLatest
。
因为你不关心来自rac_signalForSelector
的值,你可以使用mapReplace
运算符来区分method1
和method2
:
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
}
}];
我发现这种方法对于处理 "opposite" 事件很有用,例如带有参数 UIControlEventTouchDownInside
和 UIControlEventTouchUpInside
的 rac_signalForControlEvents
。
如标题所述,有没有办法执行以下操作:
[[RACSignal combineLatest:@[signal1, signal2]] subscribNext:^id(RACTuple *signals) {
// Did signal1 or signal2 emit an event?
}];
所以在 subscribeNext 块中,我目前不知道触发了哪个信号。
我试图解决的问题涉及为选择器生成信号(使用 rac_signalForSelector),我希望在这些方法中的任何一种被触发时得到通知。我想将事件合并在一起,但除了实际调用的方法之外,我不想要任何事件的最新值。
例如
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?
}];
假设您示例中的 signal1
和 signal2
正在发送相同类型的值,并且您想对每个信号的值执行相同的操作,您可以使用 merge:
而不是 combineLatest:
以获得每个触发的值的信号:
[[RACSignal merge:@[signal1, signal2]] subscribeNext:^(NSObject *latestValue) {
NSLog(@"%@", latestValue);
}];
如果您想区别对待它们,则根本不需要使用 combineLatest:
或 merge:
-- 您可以单独订阅每一个。
请注意 merge:
和 combineLatest:
之间的一个区别是,对于 merge:
,您的块将在第一个方法被调用时立即被调用——它不会等到每个方法在开始触发之前至少被调用一次,就像 combineLatest:
那样。如果需要这种行为,可以使用 then:
运算符来实现。
如果您做不仅需要知道"most recently invoked"方法的参数而且还参数从上次调用其他方法开始,您确实需要等到每个方法至少被调用一次……您可以做的一件事是将每个信号映射到 (id whateverTheyActuallySent, NSUInteger sharedMonotonicallyIncreasingIdentifier)
的元组中,然后组合 那些信号,然后根据该标识符对它们进行排序。
这将是...不雅观,但只有在非常奇怪的情况下才能保证这样做,如果您确实认为这是最好的方法,那么最好再缩小一个级别,看看是否可以更改其他内容这样您就不必这样做了。
正如 Ian 在他的回答中提到的,您可能想使用 merge
而不是 combineLatest
。
因为你不关心来自rac_signalForSelector
的值,你可以使用mapReplace
运算符来区分method1
和method2
:
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
}
}];
我发现这种方法对于处理 "opposite" 事件很有用,例如带有参数 UIControlEventTouchDownInside
和 UIControlEventTouchUpInside
的 rac_signalForControlEvents
。