2015-04-15 39 views
1

我正在尝试将我的iOS应用程序重构为ReactiveCocoa和ReactiveViewModel,并且努力尝试制定一些最佳实践。使用ReactiveCocoa重试命令

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

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

在我的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而不是?

有没有更好的方法?

回答

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]. 

您还可以使用RAC补充UIButton并结合self.viewModel.loadStationsCommandretry按钮rac_command

有一个很好的article which explains RACCommand,并显示一些有趣的模式与它一起使用。