Objective c ReactiveCocoa takeUntil和takeWhile不';“不要最后发送”;“下一步”;

Objective c ReactiveCocoa takeUntil和takeWhile不';“不要最后发送”;“下一步”;,objective-c,reactive-programming,reactive-cocoa,Objective C,Reactive Programming,Reactive Cocoa,考虑以下代码段: - (RACSignal *)startRouting { ... } - (RACSignal *)updateRoutingWithSession:(NSString *)session { ... } - (RACSignal *)fetchFlights { return [[self startRouting] flattenMap:^RACStream *(NSString *session) { return [[[[self upda

考虑以下代码段:

- (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
返回一个
RACSignal
,它发送一个会话ID。
updateRoutingWithSession:
返回一个
RACSignal
,该信号发送一个
NSDictionary
外观,包括
PercentComplete
属性。两次投票之间有两秒钟的延迟

fetchFlights
将一直运行,直到
updateRoutingWithSession:
PercentComplete
为100

我这里的问题是,最后一个
sendNext:
,其中
takentilblock
返回
true
,没有到达
RACSubscriber


我遗漏了什么?

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

我在RX的世界里发现了这一点。这通常通过合并两个信号来解决。在谓词为真之前接受重复源的语句。另一个在谓词为true时跳过

这看起来像这样

 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.
合并的
信号将
发送下一个
每个
下一个
中,包括最后一个。然后
发送完成

RX世界的一些参考资料:


绝对正确。我可以做的是不使用takeUntilBlock,而是将谓词移动到updateRoutingWithSession:中,并且只有sendComplete:一旦PercentComplete为100。但这会破坏updateRoutingWithSession的逻辑流:它不知道高阶函数如何使用它,也就是说,它不知道在服务完成之前轮询服务。@HansSjunnesson我认为@allprog试图指出,您可以在这里使用
completed
事件来确定
takentilblock:
何时返回
NO
。您可以通过
-subscribebecomplete:
或类似的运算符来执行此操作。@JustinSpahr Summers True,但completed不会发送任何数据。我对最后一个的内容感兴趣,完成信号发送的值。TakeWhile会抑制上一个
下一个
的传播。啊,对不起,我不明白那部分。在这种情况下,您可以组合一些其他运算符,如
-mapreviouswithstart:combine:
-materialize
,以保留上一个值,然后将完成本身视为一个值。