使用ReactiveCocoa查看模型更新的控制器状态更新

时间:2013-12-31 02:34:12

标签: ios reactive-cocoa

当我慢慢地试图绕过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:方法解决了这个问题。我的问题是:如何简化/重新设计?

1 个答案:

答案 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