ReactiveCocoa:处理重复信号

时间:2014-01-18 14:24:19

标签: ios objective-c reactive-cocoa

我正在尝试了解如何处理计划在后台线程上运行的RACSignal。

// Start button
@weakify(self);
[[self.startButton rac_signalForControlEvents:UIControlEventTouchUpInside] subscribeNext:^(UIButton *sender) {
    @strongify(self);
    self.startButton.enabled = NO;
    NSDate *startDate = [NSDate date];
    RAC(self, elapsedTime) = [[[[RACSignal interval:0.1f onScheduler:
                                 [RACScheduler schedulerWithPriority:RACSchedulerPriorityDefault]]
                                startWith:[NSDate date]] map:^id(id value) {
        NSTimeInterval timeInterval = [(NSDate *)value timeIntervalSinceDate:startDate];
        return [NSNumber numberWithDouble:timeInterval];
    }] deliverOn:[RACScheduler mainThreadScheduler]];
}];

// Stop button
[[self.stopButton rac_signalForControlEvents:UIControlEventTouchUpInside] subscribeNext:^(id x) {
    self.startButton.enabled = YES;

    // How do I stop the timer here...???

}];

RAC(self.timeLabel, text) = [RACObserve(self, elapsedTime) map:^id(NSNumber *number) {
    NSString *string = [NSString stringWithFormat:@"%.1f sec. elapsed", number.floatValue];
    return string;
}];

以上代码执行以下操作:

  • 将RACCommand绑定到启动RACSignal的按钮
  • RACSignal绑定到NSNumber(elapsedTime),每隔0.1秒发送一个新值。
  • 最后我有一个timeLabel绑定到这个数字,让我在屏幕上显示一个每0.1秒更新一次的计时器。

我想要做的是在单击START和STOP按钮时启动和停止计时器。问题是我不明白如何处理信号。

2 个答案:

答案 0 :(得分:8)

通常,当您想要阻止信号继续发送事件时,您将需要使用takeUntil:运算符。这只是一个粗略的例子,可能会使用更多的东西,但这应该有效:

@weakify(self);
[[self.startButton rac_signalForControlEvents:UIControlEventTouchUpInside] subscribeNext:^(UIButton *sender) {
    @strongify(self);
    self.startButton.enabled = NO;
    NSDate *startDate = [NSDate date];
    RAC(self, elapsedTime) = [[[[[RACSignal interval:0.1f onScheduler:
                                 [RACScheduler schedulerWithPriority:RACSchedulerPriorityDefault]]
                                startWith:[NSDate date]] 
                                takeUntil:[self.stopButton rac_signalForControlEvents:UIControlEventTouchUpInside]] map:^id(id value) {
        NSTimeInterval timeInterval = [(NSDate *)value timeIntervalSinceDate:startDate];
        return [NSNumber numberWithDouble:timeInterval];
    }] deliverOn:[RACScheduler mainThreadScheduler]];
}];

答案 1 :(得分:1)

只需使用takeWhileBlock并设置shouldReapeatSignalActive

等标记即可
takeWhileBlock:^BOOL(id x) {
        @strongify(self);
        return shouldReapeatSignalActive;
}

shouldReapeatSignalActive设置为NO时, 所有订阅者都将取消订阅信号(除非您重新订阅信号)。

相关问题