Mike
Mike

Reputation: 63

ReactiveCocoa: disposing of a repeating signal

I'm trying to understand how to dispose of a RACSignal that is scheduled to run on a background thread.

// 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;
}];

The above code does the following:

What I would like to do is being able to start and stop the timer when clicking the START and STOP buttons. Problem is I don't understand how to dispose of the signal.

Upvotes: 6

Views: 4129

Answers (2)

user3044484
user3044484

Reputation: 503

Just using takeWhileBlock and setting a flag like shouldReapeatSignalActive

takeWhileBlock:^BOOL(id x) {
        @strongify(self);
        return shouldReapeatSignalActive;
}

when shouldReapeatSignalActive set to NO, all subscribers will all unsubscribe the signal anymore (unless you resubscribe the signal).

Upvotes: 1

Ash Furrow
Ash Furrow

Reputation: 12421

Usually when you want to stop a signal from continuing to send events, you'll want to use the takeUntil: operator. This is just a crude example, and could probably use a little more finessing, but this should work:

@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]];
}];

Upvotes: 8

Related Questions