使用ReactiveCocoa重试命令

时间:2015-04-15 02:23:11

标签: ios objective-c reactive-cocoa raccommand

我试图将我的iOS应用重构为ReactiveCocoa和ReactiveViewModel,并且我正在努力尝试制定一些最佳做法。

我将这归结为一个简单的用例 - 我要推送一个视图控制器,它加载一些数据并将其推送到表格视图中。如果端点调用因任何原因失败,我想在屏幕上显示一个带有重试按钮的视图。

我目前有这个工作,但它看起来有点污秽。我觉得必须有更好的方法 - 我是否正确地做到了这一点?

在我的ViewModel的init方法中,我创建了我的命令,一旦ViewModel变为活动状态,就会调用该命令。

// create the command to load the data
@weakify(self);
self.loadStationsCommand = [[RACCommand alloc] initWithSignalBlock:^(RACSignal *(id input) {
    @strongify(self);
    return [RACSignal createSignal:^(RACDisposable *(id<RACSubscriber subscriber) {
        // load data from my API endpoint
        ...
        BOOL succeeded = ...;
        if (succeeded) {
            [subscriber sendNext:nil];
            [subscriber sendCompleted:nil];
        } else {
            // failed
            [subscriber sendError:nil];   
        }
        return nil;
    }
}];

// start the command when the ViewModel's ready
[self.didBecomeActiveSignal subscribeNext:^(id x) {
    @strongify(self);
    [self.loadStationsCommand execute:nil];
}];

在我的UIViewController中,我通过 -

订阅命令
[self.viewModel.loadStationsCommand.executionSignals subscribeNext:^(RACSignal *loadStationsSignal) {
    [loadStationsSignal subscribeNext:^(id x) {
        // great, we got the data, reload the table view. 
        @strongify(self);
        [self.tableView reloadData];
    } error:^(NSError *error) {
        // THIS NEVER GETS CALLED?!
    }];
}];

[self.viewModel.loadStationsCommand.errors subscribeNext:^(id x) {
    // I actually get my error here. 
    // Show view/popup to retry the endpoint.
    // I can do this via [self.viewModel.loadStationsCommand execute:nil]; which seems a bit dirty too.
}];

我必须对RACCommand如何运作有一些误解,或者至少我觉得我没有尽可能干净地做到这一点。

为什么我的loadStationsSignal上的错误阻止没有被调用?为什么我需要订阅executionCommand.errors

有更好的方法吗?

1 个答案:

答案 0 :(得分:2)

这是使用RACCommand处理错误的正确方法。正如您在docs中所读到的那样,使用executionSignals时不会发送内部信号的错误:

 Errors will be automatically caught upon the inner signals, and sent upon
 `errors` instead. If you _want_ to receive inner errors, use -execute: or
 -[RACSignal materialize].

您还可以对UIButton使用RAC添加,并将self.viewModel.loadStationsCommand绑定到rac_command按钮的retry

有一个很好的article which explains RACCommand,并展示了一些有趣的模式。