Sapan Diwakar

Software developer

Follow me on Twitter Check out my code on GitHub View some of my designs on Dribbble Take a look at my Linked In profile

Best Practices for Table View Data Sources

If you read objc.io, you already know what I am talking about, lighter view controllers. Table views are heavily used in iOS apps and most of the times, all the code for handling the data source goes right in the controller. As the app starts growing, the controllers become these huge files that you wouldn't want to touch.

There are several libraries out there to take out the redundant data source code out from the controllers. SSDataSources is one such library that I have been using and its great. It is a collection of objects that conform to UITableViewDataSource and UICollectionViewDataSource.

Its really simple to use in your app. Just create table view cells that extend SSBaseTableCell and override identifier to return the reuse identifier for this cell. All you need now in your controller is to create an instance of SSDataSource (e.g. SSArrayDataSource) and set the cellConfigureBlock to configure the cell. Finally, set the tableView property of the data source to the table view you want this data source to be associated to.

Its also pretty cool when you need to manage multiple sections, (e.g. one section for the data, one for the cell to indicate loading). Just create a sectioned data source:

self.dataSource = [[SSSectionedDataSource alloc] init];  
self.dataSection = [[SSSection alloc] init];  
self.loadingSection = [[SSSection alloc] init];  
[self.dataSource appendSection:self.dataSection];
[self.dataSource appendSection:self.loadingSection];

// Configure data source
self.dataSource.cellCreationBlock = ^id(id object, UITableView *tableView, NSIndexPath *indexPath) {  
    if ([object isKindOfClass:[MyData class]]) {
        return [MyDataTableViewCell cellForTableView:tableView];
    } else {
        return [GMLoadingTableViewCell cellForTableView:tableView];
    }
};
self.dataSource.cellConfigureBlock = ^(SSBaseTableCell *cell, id object, UITableView *tableView, NSIndexPath *indexPath) {  
    if ([cell isKindOfClass:[MyDataTableViewCell class]]) {
        [((MyDataTableViewCell *) cell) configureForData:object];
    }
};
// Disable editing
self.dataSource.tableActionBlock = ^BOOL(SSCellActionType actionType, UITableView *parentView, NSIndexPath *indexPath) {  
    return NO;
};
self.tableView.dataSource = self.dataSource;  

And when you are loading some data, add a cell to the loading section.

// Loading some data?
self.loadingSection.items = page > 1 ? [NSMutableArray arrayWithObject:@"Loading"] : nil;  
[self.tableView reloadSections:[NSIndexSet indexSetWithIndex:1] withRowAnimation:UITableViewRowAnimationNone];