Question

I'm currently doing something like this to progressively iterate through an array as it is modified:

    [[[[RACObserve(self, match.moves) combinePreviousWithStart:@[] reduce:^id(NSArray * previous, NSArray * current) {
        NSArray * newMoves = current;
        if (previous.count > 0) {
            newMoves = _.tail(current, current.count - previous.count);
        }
        return [newMoves.rac_sequence.signal flattenMap:^RACSignal*(CCXMove * move) {
            return [RACSignal return:move];
        }];
    }] concat] delay:1] subscribeNext:^(id move) {
        @strongify(self);
        NSLog(@"next %lu called", (unsigned long)[self.match.moves indexOfObjectIdenticalTo:move]);
    }];

However it looks like the way delay works is that the current next call will just be delayed by 1 second rather than the desired effect of each next happening at least 1 second after the previous execution completed. Output:

    2014-04-01 21:38:15.820 RACPlayground[74040:60b] self.match.moves updated
    2014-04-01 21:38:16.823 RACPlayground[74040:1303] next 0 called
    2014-04-01 21:38:16.824 RACPlayground[74040:1303] next 1 called
    2014-04-01 21:38:16.824 RACPlayground[74040:1303] next 2 called
    …

There is a 1 second delay between the array being modified and the first next call, but then all subsequent calls are immediate rather than also being delayed.

Edit for posterity, with Dave Lee's help a working solution is below:

    [[[RACObserve(self, match.moves) combinePreviousWithStart:@[] reduce:^id(NSArray * previous, NSArray * current) {
        NSArray * newMoves = current;
        if (previous.count > 0) {
            newMoves = _.tail(current, current.count - previous.count);
        }
        RACSignal *emptyDelay = [[RACSignal empty] delay:1];
        RACSequence *delayedMoves = [newMoves.rac_sequence map:^(CCXMove *move) {
            return [emptyDelay concat:[RACSignal return:move]];
        }];
        return [RACSignal concat:delayedMoves];
    }] concat] subscribeNext:^(CCXMove * move) {
        @strongify(self);
        NSLog(@"processing move %lu", (unsigned long)[self.match.moves indexOfObjectIdenticalTo:move]);
    }];

    NSLog(@"appending a two objects one at a time");
    self.match.moves = [self.match.moves arrayByAddingObject:@1];
    self.match.moves = [self.match.moves arrayByAddingObject:@2];

    NSLog(@"appending two objects at the same time");
    self.match.moves = [self.match.moves arrayByAddingObjectsFromArray:@[@3, @4]];

Output:

    2014-04-01 23:31:34.042 RACPlayground[79495:60b] appending a two objects one at a time
    2014-04-01 23:31:34.044 RACPlayground[79495:60b] appending two objects at the same time
    2014-04-01 23:31:35.044 RACPlayground[79495:1303] processing move 0
    2014-04-01 23:31:36.045 RACPlayground[79495:1303] processing move 1
    2014-04-01 23:31:37.046 RACPlayground[79495:1303] processing move 2
    2014-04-01 23:31:38.047 RACPlayground[79495:1303] processing move 3
Was it helpful?

Solution

After a couple of not quite right answers, here is a change you can make that will (I think) actually do what you asked:

RACSignal *emptyDelay = [[RACSignal empty] delay:1];
RACSequence *delayedMoves = [newMoves.rac_sequence map:^(CCXMove *move) {
    return [emptyDelay concat:[RACSignal return:move]];
}];
return [RACSignal concat:delayedMoves];
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top