当我慢慢地试图绕过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
,属性tasks
属于NSArray
。项目有tasks
信号,返回MyTask
个数组。项目可以随时从外部进行更改。我希望我的视图控制器在发生所述情况时做出响应并自行刷新。
问题我试图解决:
我曾经在第一个区块内[[project tasks] subscribeNext:...]
,直到我意识到如果webrequest花了太长时间并且我在此期间切换了项目,我在新的上下文中接收并分配了旧项目的数据! (此后不久,新数据集到了,一切都恢复正常)。
然而,这就是我遇到的问题,我使用takeUntilBlock:
方法解决了这个问题。我的问题是:如何简化/重新设计?
答案 0 :(得分:4)
最自然地承担最新项目任务的关键操作员是-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
,以及在{中处理错误的简单方法{1}}信号。
-tasks