我在 ReactiveCocoa 的世界里还是个新手,我只是想弄清楚这个常见的场景。我注意到其他人在 GitHub 和 SO 上都在努力解决这个问题,但我仍然没有找到合适的答案。
以下示例确实有效,但我看到 Justin Summers 说订阅中的订阅或一般的订阅可能是代码味道。因此,我想在学习这种新范式时尽量避免坏习惯。
因此,示例(使用 MVVM)非常简单:
- ViewController 包含一个登录按钮,该按钮连接到 View 模型中的登录命令
- ViewModel 指定命令操作并为此示例模拟一些网络请求。
- ViewController 订阅命令的执行信号并能够区分三种类型的返回:下一步、错误和完成。
还有代码。
1( View Controller ):
RAC(self.loginButton, rac_command) = RACObserve(self, viewModel.loginCommand);
2( View 模型):
self.loginCommand = [[RACCommand alloc] initWithEnabled:canLoginSignal
signalBlock:^RACSignal *(id input) {
return [[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
BOOL success = [username isEqualToString:@"user"] && [password isEqualToString:@"password"];
// Doesn't really make any sense to use sendNext here, but lets include it to test whether we can handle it in our viewmodel or viewcontroller
[subscriber sendNext:@"test"];
if (success)
{
[subscriber sendCompleted];
} else {
[subscriber sendError:nil];
}
// Cannot cancel request
return nil;
}] materialize];
}];
3( View Controller ):
[self.viewModel.loginCommand.executionSignals subscribeNext:^(RACSignal *execution) {
[[execution dematerialize] subscribeNext:^(id value) {
NSLog(@"Value: %@", value);
} error:^(NSError *error) {
NSLog(@"Error: %@", error);
} completed:^{
NSLog(@"Completed");
}];
}];
你会如何以一种更像 ReactiveCococa 的方式来做到这一点?
最佳答案
RACCommand
的工作方式,值来自 executionSignals
信号,错误来自 errors
信号,以及完成,嗯,那些是在您的示例中,人们可能会使用 -materialize
和 -dematerialize
。
在给出的例子中,登录,可以说它不需要完成来建模。相反,可以将登录信号定义为二进制行为:它要么发送 @YES
(例如),要么发送错误。在这些条件下,代码将是:
[[self.viewModel.loginCommand.executionSignals concat] subscribeNext:^(id _) {
// Handle successful login
}];
[self.viewModel.loginCommand.errors subscribeNext:^(NSError *error) {
// Handle failed login
}];
这显然与 RAC 中典型的 subscribeNext:error:completed:
模式有点不同。这完全是由于 RACCommand
的 API。
请注意,-concat
运算符已应用于 executionSignals
以显示内部值并避免内部订阅。您可能还会看到 -flatten
或 -switchToLatest
在其他 RACCommand
示例中使用,但只要命令有其 allowsConcurrentExecution
属性设置为 NO
(这是默认值),然后执行顺序发生,使 -concat
成为自然匹配和表达这些串行语义的运算符。应用 -flatten
或 -switchToLatest
实际上会起作用,因为它们在应用于串行信号信号时退化为 -concat
,但它们表示对读者来说不适用的语义。
关于ios - 在 ReactiveCocoa 中处理下一步、完成和错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26383918/