ReactiveCocoa takeUntil和takeWhile不发送最后一个“下一个”

时间:2013-04-03 10:40:51

标签: objective-c reactive-programming reactive-cocoa

请考虑以下代码段:

- (RACSignal *)startRouting {
...
}

- (RACSignal *)updateRoutingWithSession:(NSString *)session {
...
}

- (RACSignal *)fetchFlights {
    return [[self startRouting] flattenMap:^RACStream *(NSString *session) {
        return [[[[self updateRoutingWithSession:session]
                        delay:2.0f]
                        repeat]
                        takeUntilBlock:^BOOL(RACTuple *operationAndResponse) {
                            AFHTTPRequestOperation *operation = [operationAndResponse first];
                            NSDictionary *response = [operationAndResponse second];
                            return [operation isCancelled] || 100 == [response[kPercentComplete] intValue];
                        }];
    }];
}

这里发生的是startRouting返回发送会话ID的RACSignalupdateRoutingWithSession:会返回RACSignal,其中NSDictionary会发送包含PercentComplete属性的fetchFlights。民意调查之间有两秒钟的延迟。

updateRoutingWithSession:将一直运行,直到PercentComplete的{​​{1}}为100。

我的问题是,sendNext:返回takeUntilBlock的最后true未到达RACSubscriber

我错过了什么?

2 个答案:

答案 0 :(得分:2)

我在RX的世界里发现了这个。这通常通过合并两个信号来解决。采用重复源直到谓词为真的。而另一个在谓词为真时跳过。

这看起来像这样

 BOOL (^finished)(id _) = ^BOOL(id _) {
    return predicate; // BOOLean here
}

// You want a multicast signal, because multiple signals will subscribe to the source.
// Multicasting it means that you won't get repeated api-requests, in this case.
RACMulticastConnection *source = [[theSignal repeat] publish];

RACSignal *whileNotDone = [source.signal takeUntilBlock:finished];
RACSignal *whenDone = [[source.signal skipUntilBlock:finished] take:1];
RACSignal *merged = [RACSignal merge:@[whileNotDone, whenDone]];

[source connect]; // Needed for a multicast signal to initiate.

merged信号将sendNext next source sendCompleted包括最后一个信号。然后是{{1}}。

来自RX世界的一些参考文献:

答案 1 :(得分:1)

澄清一下:您的问题是触发完成的next是否已发送出去? takeUntilBlock将传播nexts,直到谓词为NO。 (documentation)因此,不会发送最后一个next。但是你可以订阅completion,在这种情况下会发生这种情况。