在ReactiveCocoa中链接相关的信号

在ReactiveCocoa中,如果我们链接几个依赖信号,我们必须使用subscribeNext:链中的下一个信号来接收生成的前一个信号的值(例如asynchronous操作的结果)。 所以一段时间后,代码变成这样的东西(不必要的细节被省略):

 RACSignal *buttonClickSignal = [self.logIn rac_signalForControlEvents:UIControlEventTouchUpInside]; [buttonClickSignal subscribeNext:^(UIButton *sender) { // signal from a button click // prepare data RACSignal *loginSignal = [self logInWithUsername:username password:password]; // signal from the async network operation [loginSignal subscribeNext:^void (NSDictionary *json) { // do stuff with data received from the first network interaction, prepare some new data RACSignal *playlistFetchSignal = [self fetchPlaylistForToken:token]; // another signal from the async network operation [playlistFetchSignal subscribeNext:^(NSDictionary *json) { // do more stuff with the returned data }]; // etc }]; }]; 

这个不断增加的嵌套看起来不如文档中给出的非react native示例好得多:

 [client logInWithSuccess:^{ [client loadCachedMessagesWithSuccess:^(NSArray *messages) { [client fetchMessagesAfterMessage:messages.lastObject success:^(NSArray *nextMessages) { NSLog(@"Fetched all messages."); } failure:^(NSError *error) { [self presentError:error]; }]; } failure:^(NSError *error) { [self presentError:error]; }]; } failure:^(NSError *error) { [self presentError:error]; }]; 

我错过了什么吗? 在ReactiveCocoa中有更好的链式依赖工作模式吗?

这是RACStream和RACSignal运营商开始真正派上用场的时候。 在您的具体示例中,您可以使用-flattenMap:将结果合并到新信号中:

 [[[buttonClickSignal flattenMap:^(UIButton *sender) { // prepare 'username' and 'password' return [self logInWithUsername:username password:password]; }] flattenMap:^(NSDictionary *json) { // prepare 'token' return [self fetchPlaylistForToken:token]; }] subscribeNext:^(NSDictionary *json) { // do stuff with the returned playlist data }]; 

如果您不需要任何步骤的结果,您可以使用-sequenceMany:-sequenceNext:来代替类似的效果(但是为了更清楚地expression意图)。