使用反应可可查看模型更新的控制器状态更新



当我慢慢尝试围绕ReactiveCocoa时,我写了这段代码,我相当确定有更好的方法来解决我的问题。我将不胜感激有关如何改善/重新设计我的情况的意见。

@weakify(self);
[RACObserve(self, project) subscribeNext:^(MyProject *project) {
@strongify(self);
self.tasks = nil;
[[[project tasks] takeUntilBlock:^BOOL(NSArray *tasks) {
if ([tasks count] > 0) {
MyTask *task = (MyTask *)tasks[0];
BOOL valid = ![task.projectID isEqualToString:self.project.objectID];
return valid;
}
return NO;
}] subscribeNext:^(NSArray *tasks) {
self.tasks = tasks;
}];
}];

这是做什么的:

我有一个视图控制器,其中包含一个名为project的属性,类型为MyProject,属性tasksNSArray类型。项目有一个返回MyTasks 数组的tasks信号。该项目可以随时从外部更改。我希望我的视图控制器在发生上述情况时响应并刷新自身。

我正在尝试解决的问题:

我曾经在第一个块中[[project tasks] subscribeNext:...],直到我意识到如果 webrequest 花费的时间太长并且我在此期间切换了项目,我会在新上下文中从旧项目接收并分配数据!(此后不久,新的数据集到达,一切恢复正常)。

尽管如此,这就是我遇到的问题,我使用takeUntilBlock:方法解决了它。我的问题是:我如何简化/重新设计它?

最自然地承担最新项目任务的关键运算符是-switchToLatest。此运算符获取信号的信号,并返回仅发送从最新信号发送的值的信号。

如果这听起来太抽象,那么将其放在您的域中会有所帮助。首先,您有项目的信号,特别是RACObserve(self, project)。然后,您可以将此项目信号-map:为包含调用-tasks的结果的信号,该信号恰好返回一个信号。现在你有一个信号信号。将-switchToLatest应用于任务信号的信号将为您提供任务信号,但仅发送来自最新项目的任务,而不是来自先前分配的项目的"旧"任务。

在代码中,这看起来像:

[[RACObserve(self, project)
map:^(MyProject *project) {
return [project tasks];
}]
switchToLatest];

可以应用的另一个用于简化代码的习惯用法是使用RAC()宏,该宏分配给属性,同时避免显式订阅。

RAC(self, tasks) = [[RACObserve(self, project)
map:^(MyProject *project) {
return [project tasks];
}]
switchToLatest];

更新

为了解决注释中的问题,下面是一个示例,说明如何在项目更改后初始化tasks属性以nil,以及处理-tasks信号中的错误的简单方法。

RAC(self, tasks) = [[RACObserve(self, project)
map:^(MyProject *project) {
return [[[project
tasks]
startsWith:nil]
catch:^(NSError *error) {
[self handleError:error];
return [RACSignal return:nil];
}];
}]
switchToLatest];

最新更新