Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What are the benefits of separating Data Source from UITableViewController?

I have read that separating Data Source from ViewController is a good idea, as it reduces code bloat and coupling.

So I decided to make a separate object as my TableView data source. All was fine and dandy until I needed these:

  1. I need pointer to my table view in order to reload it when new data arrives. This alone makes this decoupling thing difficult, since data source knows about table view and via it about the view controller.

  2. Now I need to show detail view controller on tap. Now I need pointer for current view controller. This can be done via table view, or as separate property.

So these two things in my mind remove any decoupling or separation, and only add complications.

What are the benefits of separating data source over using in view controller?

like image 742
Dvole Avatar asked Mar 19 '23 19:03

Dvole


1 Answers

As you are undoubtedly familiar of the Model View Controller paradigm, separating the TableView data source from the controller does not simply reduce bloat and the dreaded "Massive ViewController" problem. It actually promotes data source reusability and clarifies the responsibility of your controller.

That being said there was a fantastic talk at this years WWDC titled "Advanced User Interfaces With Collection Views" (Session 232). I urge you to watch this video because in it we get the first real glimpse of architectural patterns employed by the iOS Teams at Apple.

In the video you will see that their collection view cells are actually returned from the data source. Taking this one step further they actually create aggregate datasources that compose several datasources into a common model. This way you end up with an architecture that allows you to reuse cells in any view controller. All that is needed is to set up the appropriate data sources.

Regarding your first point : Needing a pointer to the tableview. This is not true. Your data source can communicate to the controller via a delegate callback, notifying the controller to reload the cells at certain index paths.

Again, if you need to handle tap events thats also easy, the tap handling can still reside in your controller. You could simply ask your data source for which controller to return for a given index path.

As a simple example, imagine we have a tableview showing a list of the top films in the box office and their live ratings.

Now we want to create our datasources. The datasource should be responsible for fetching the information from the server, returning the appropriate cell configured with the right data, and registering reusable cells with a table view. This information is also live and so might update at any time so the data source needs to communicate to the controller to signal updates.

So our film data source might look like this:

@interface FilmDataSource : NSObject<UITableViewDataSource>
@property (assign,nonatomic) id<FilmDataSourceDelegate> delegate;
- (void)registerReusableViewsWithTableView:(UITableView *)tableView;
- (void)reloadContent;
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath;
@end

@protocol FilmDataSourceDelegate <NSObject>
- (void)dataSource:(FilmDataSource *)dataSource didUpdateItemsAtIndexPaths:(NSArray *)indexPaths;
- (void)dataSourceDidRequestReload:(FilmDataSource *)dataSource;
@end

Remember the data source will also know whether any of the requests failed and so can potentially return a cell with a retry button. The data source could handle the request for refresh and trigger an update to the controller when it fetches information.

Naturally this design becomes more attractive as you start to decide on multiple data sources. The trick is to look at what cells in the table view should belong to a particular data source because the key here is in promoting reusability. Then you can move on to designing an aggregate datasource that manages its own children.

like image 193
Daniel Galasko Avatar answered Apr 06 '23 05:04

Daniel Galasko