I am using VIPER architecture for my recent project. But I am wondering how to implement UITableView DataSource.
In VIPER, View is passive. They send event to Presenter, then Presenter send proper ViewData(ViewModel) to View.
So I stored ViewModels for tableView in View. (View doesn't ask data to Presenter.)
class View: UIViewController, UITableViewDataSource {
var viewModels: [CellViewModelType] = []
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return viewModels.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let viewModel = viewModels[indexPath.row]
let cell = tableView.dequeueReusableCell(withIdentifier: "reuseIndetifier", for: indexPath)
cell.configure(with: viewModel)
return cell
}
}
When user selects item in tableView, View send didSelectItemAt
event with indexPath to Presenter. Then Presenter decides proper action for event, push VC or fetch data.
So Presenter should know ViewData (or Real Data). Or Presenter pass event to Interactor, because Interactor stores Real Data.
Here is my dilemma for synchronization. Data is spread View, Presenter, Interactor. They may be different, because Real Data can be changed asynchronously in background (like chat app). Because locking would be entirely inappropriate, how do I assure stateful data integrity among multiple threads in a VIPER architecture?
Any help would be greatly appreciated. :D
Am I right that you are afraid of inconsistency of data in ViewModels array and Data array in Presenter or Interactor? If so, when new data have been fetched by Interactor, it's passed to Presenter. There I prefer to synchronously send it to View as ViewModels first, then set it to Presenter's Data array. And when you call
didSelectCellAtIndexPath:
and send event with IndexPath to Presenter, additional checks in accessing data from Data array are a good idea.