2015-04-24 49 views
2

几次阅读-flattenMap的README后,我仍然不知道为什么这个代码没有按预期执行。我应该认为块内部的代码会运行两次,但根本没有被打到。我错过了一些非常愚蠢的事情吗? (我正在使用v2.4.7)我也试过在我调用-flattenMap之后发送这些值,以防止它是订单。没有骰子。这个简单的`-flattenMap` ReactiveCocoa代码有什么问题?

RACSubject *test = [[RACSubject alloc] init]; 
[test sendNext:@1]; 
[test sendNext:@2]; 
[test sendCompleted]; 
[test flattenMap:^RACStream *(id value) { 
    NSLog(@"here: %@", value); 
    return [RACSignal return:@NO]; 
}]; 

回答

2

两件事情:

的顺序做的事情,因为这是一个问题,所以改成这样:

RACSubject *test = [[RACSubject alloc] init]; 
[test flattenMap:^RACStream *(id value) { 
    NSLog(@"here: %@", value); 
    return [RACSignal return:@NO]; 
}]; 
[test sendNext:@1]; 
[test sendNext:@2]; 
[test sendCompleted]; 

现在,你仍然不会看到任何东西 - - 因为你还没有订阅它。你只是创建了一个信号,可以做这一切,但它会延迟实际上做任何工作,直到你要求它。

RACSubject *test = [[RACSubject alloc] init]; 
[[test flattenMap:^RACStream *(id value) { 
    NSLog(@"here: %@", value); 
    return [RACSignal return:@NO]; 
}] subscribeNext:^(id value) { 
    NSLog(@"got a %@", value); 
}]; 
[test sendNext:@1]; 
[test sendNext:@2]; 
[test sendCompleted]; 

现在,因为有究竟是谁想要了解值的用户,这些send旨意触发适当的。

将来,请避免在subscribe*do*方法系列的块之外的任何位置添加副作用(如日志记录)。 flattenMap和其他combinators希望是纯粹的,所以你会看到这样的意外行为,如果你违反了这一点。

你可能知道这一点,只是要测试出flattenMap,而您的代码可以简化为只需map在这里 - flattenMap + return == map

+0

Facepalm。是的,这是有道理的,并感谢一吨。所以为了确保我的条款是正确的,这种行为反映了它是一个热门信号,还是完全不同的概念? – eremzeit

+1

@eremzeit我相信这是正确的,但倒置。你用flattenMap得到的信号是* cold *信号。直到有人订阅它,它才会做任何事情。当他们(或者应该)像这样完全纯净时,讨论热信号和冷信号是很奇怪的,但是 - 我认为一个更合适的例子就像网络请求。如果您创建表示GET请求的热门信号,则无论是否有人订阅该请求,都会执行该请求。然而,一个冷的GET信号会等待某人“请求”请求的结果以启动请求。 –