NUCLiOS IGGridView: Custom Header Cell for Sorting

Stephen Zaharuk / Tuesday, October 7, 2014

If you're using the IGGridViewDataSourceHelper classes you may know that you can use it to sort the data in your IGGridView. However, we don't currently offer a built in interaction to do the sorting for your user. 

Because of the pure flexibility of the IGGridView, its pretty simple to add it yourself. 

To start off, we're going to create 2 interfaces (classes) and 1 protocol( interface):

@protocol SortingDelegate <NSObject>

-(void)gridView:(IGGridView*)gridView toggleColumnSorting:(NSInteger)columnIndex;

@end

@interface ExtendedDSH : IGGridViewDataSourceHelper<SortingDelegate>

@end

@interface CustomHeaderCell : IGGridViewHeaderCell

@property(nonatomic, weak)id<SortingDelegate> delegate;

-(void)setSortDirection:(IGGridViewSortedColumnDirection)direction;

@end

In the code above, i'm creating a custom header cell, which we'll use to display a sort indicator and handle a tap gesture. Then  i'm declaring a DataSourceHelper that derives from our base IGGridViewDataSourceHelper. We'll use this class to create our CustomHeaderCell. And finally a delegate that we'll use to allow communication between the DSH and the HeaderCell

Lets next implement our HeaderCell. What we will do is define a custom view that displays as red if descending, green if ascending, and clear if its not the column being sorted.  We'll also add a tap gesture, to notify the DataSourceHelper it should toggle the sort. 

UITapGestureRecognizer* tap = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(tapped:)];

[self registerGestures:@[tap]];        

_sortIndicator = [[UIView alloc]init];

[self addSubview:_sortIndicator];

-(void)setSortDirection:(IGGridViewSortedColumnDirection)direction

{

    if(direction == IGGridViewSortedColumnDirectionAscending)

        _sortIndicator.backgroundColor = [UIColor greenColor];

    else if(direction == IGGridViewSortedColumnDirectionDescending)

        _sortIndicator.backgroundColor = [UIColor redColor];

    else

        _sortIndicator.backgroundColor = [UIColor clearColor];

}

-(void)tapped:(UITapGestureRecognizer*)gesture

{

    [self.delegate gridView:self.gridView toggleColumnSorting:self.path.columnIndex];

}

Now all we have to do is implement our DataSourceHelper. We just need to implement 2 methods. The first creates the header cell, the second implements the delegate we defined and actually applies the sorting. 

-(IGGridViewHeaderCell *)gridView:(IGGridView *)gridView headerCellAt:(NSInteger)column

{

    CustomHeaderCell* headerCell = [gridView dequeueReusableCellWithIdentifier:@"HeadeCell"];

   

    if(!headerCell)

    {

        headerCell = [[CustomHeaderCell alloc]initWithReuseIdentifier:@"HeaderCell"];

        headerCell.delegate = self;

    }

    

    headerCell.textLabel.text = [self gridView:gridView titleForHeaderInColumn:column];

    

    IGGridViewColumnDefinition* col = self.columns[column];

    IGGridViewSortedColumn* sc = (self.sortedColumns.count == 0)? nil : self.sortedColumns[0];

    if([sc.fieldName isEqualToString:col.fieldKey])

        [headerCell setSortDirection:sc.sortDirection];

    else

        [headerCell setSortDirection:IGGridViewSortedColumnDirectionNone];

    

    return headerCell;

}

-(void)gridView:(IGGridView*)gridView toggleColumnSorting:(NSInteger)columnIndex

{

    IGGridViewColumnDefinition* col = self.columns[columnIndex];

    

    IGGridViewSortedColumn* sc = nil;

    

    if(self.sortedColumns.count > 0)

    {

        sc = self.sortedColumns[0];

        [self.sortedColumns removeAllObjects];

        

        if([sc.fieldName isEqualToString:col.fieldKey])

        {

            if(sc.sortDirection == IGGridViewSortedColumnDirectionAscending)

                sc.sortDirection = IGGridViewSortedColumnDirectionDescending;

            else

                sc.sortDirection = IGGridViewSortedColumnDirectionAscending;

        }

        else

        {

            sc = [[IGGridViewSortedColumn alloc]initWithField:col.fieldKey forDirection:IGGridViewSortedColumnDirectionAscending];

        }

        

    }

    else

    {

        sc = [[IGGridViewSortedColumn alloc]initWithField:col.fieldKey forDirection:IGGridViewSortedColumnDirectionAscending];

    }

    

    [self.sortedColumns addObject:sc];

    [self invalidateData];

    [gridView updateData];

}

And thats it. 

For your convenience you can download the whole project right here

Hope this helps!

-SteveZ