NUCLIOS IGGridView: DataSourceHelpers

Stephen Zaharuk / Friday, October 3, 2014

The IGGridView is really powerful. Like the native UITableView that comes standard in iOS, it has a datasource protocol, that allows you to specify how many rows and sections you're displaying along with the ability to actually create the cell that will be displayed for a particular path. However, it adds one more dimension, the number of columns. 

So, you can implement those 4 methods:

- how many sections will you display

- how many rows per section will you display

- how many columns will you display

- create the cell for a path (row, section, column)

On top of that, there are a LOT of other methods that you can implement to handle adding/moving/deleting - rows, columns and cells. As well as creating fixed columns (both left and right), or even creating custom header cells and section cells.

Thats a LOT. Now, as powerful as that all is, its quite a bit of coding you'd have to do every time you drop a new IGGridView in your application. 

Most of the time, you're just trying to display some sort of array of data.

Thats where our DataSourceHelpers come in to play.

Essentially, the DataSourceHelpers are just that... helper classes. Its an object we created that actually implements the IGGridViewDataSource protocol that I described above. But it does all the setup work for you. 

Lets say we have an array of data that we want to display in a standard gridView. Using the dataSource protocol directly, the code may look something like this: 

_gridView.dataSource = self; // Since we're are implementing the 

-(NSInteger)gridView:(IGGridView *)gridView numberOfRowsInSection:(NSInteger)section

{

    return _data.count;

}

-(NSInteger)numberOfColumnsInGridView:(IGGridView *)gridView

{

    return 4;

}

-(IGGridViewCell *)gridView:(IGGridView *)gridView cellAt:(IGCellPath *)path

{

    IGGridViewCell* cell = [gridView dequeueReusableCellWithIdentifier:@"CELL"];

   

    igSalesmanItem* item = [_data objectAtIndex:path.rowIndex];

    

    switch (path.columnIndex) {

        case 0:

            cell.textLabel.text = item.firstName;

            break;

        case 1:

            cell.textLabel.text = item.lastName;

            break;

        case 2:

            cell.textLabel.text = item.territory;

            break;

        case 3:

            cell.textLabel.text = [NSString stringWithFormat:@"%ld", (long)item.yearToDateSales];

            break;    

        default:

            break;

    }

    

    return cell;

}

-(NSString *)gridView:(IGGridView *)gridView titleForHeaderInColumn:(NSInteger)column

{

    NSString* title = nil

    switch (column) 

    {

        case 0:

            title = NSLocalizedString(@"firstName", @"firstName");

            break;

        case 1:

            title = NSLocalizedString(@"lastName", @"lastName");

            break;

        case 2:

            title = NSLocalizedString(@"territory", @"territory");

            break;

        case 3:

            title = NSLocalizedString(@"yearToDateSales", @"yearToDateSales");

            break;    

        default:

            break;

            

    }        

    return title;

}

Now, using the dataSource helpers, to display the exact same data, we can just use this code: 

IGGridViewDataSourceHelper* ds = [[IGGridViewDataSourceHelper alloc]init];

ds.data  = data;

_gridView.dataSource = ds;

Here is the result of both:

So we took about 100 lines of code and shrunk them to 3... crazy right?

Now here is the best part... you can DO a lot more. 

The DSH handles adding/removing/moving all cells rows and columns automatically. As well as sorting, filtering, and grouping. No EXTRA work required. 

In addition, it offers what we call IGGridViewColumnDefinitions. Column Defs are exactly what they sounds like. You can actually specify which columns you want to display and in which order you want to display them. 

By default, when you set your array of data to the DatasourceHelper, it reflects on the first object on the array, and create a column for each property it finds. You can add additional columns for this, or even specify a different column type for a particular property. Or you can just turn off autoGenerateColumns on the DSH and specify your own columns manually. 

For example, lets take the example above. In my data, i have a property called "image" that actually returns an UIImage object. So in this case, lets create a image column that will be used in the grid:

IGGridViewImageColumnDefinition* col = [[IGGridViewImageColumnDefinition alloc]initWithKey:@"image" forPropertyType:IGGridViewImageColumnDefinitionPropertyTypeImage];

[ds.columnDefinitions addObject:col];

Thats it, if were to look at the results, it would look like this:

Pretty simple, right?

Now, lets say we wanted to group our data by "territory" (thats a field on my underlying data object). How hard would that be?

_dsh.groupingKey = @"territory";

Yup... just one line of code:

Pretty easy right? 

Out of the box, we actually ship more than one DataSourceHelper. We ship 3 total, and you could extend them to make more. In fact the other 2 derive from our base DataSourceHelper and just tweak them. 

My colleague Darrell wrote a post not to long ago about transposing rows/columns by deriving from our base datasource helper. Its a good read if you have time. 

Lets take a quick look at how hard it would be to take our existing code, and swap it to use another datasource helper:

IGGridViewImageColumnDefinition* col = [[IGGridViewImageColumnDefinition alloc]initWithKey:@"image" forPropertyType:IGGridViewImageColumnDefinitionPropertyTypeImage];

_dsh = [[IGGridViewSingleFieldMultiColumnDataSourceHelper alloc]initWithField:col];

_dsh.numberOfColumns = 5;

_dsh.data = [igSalesmanItem generateData:200];

_gridView.dataSource = _dsh;

So, yea... its just one more property that we have to fill out. How many columns do we want to display. In this case, we'll just say 5. 

Note: the SingleFieldMultiColumnDataSourceHelper takes a parameter in its initializer. It actually only displays one field, so you need to specify the column that you want to display. 

There you go, thats a brief look at the power of the IGGridView and it's DataSourceHelpers.

-SteveZ