2015-04-15 45 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,並顯示一些有趣的模式與它一起使用。