I followed some advice on another post and used CALayers instead of drawRect.
/**
* Draw layers
*/
-(void)drawLayers
{
for(CellLayer *layer in layerArray) {
[layer removeFromSuperlayer];
}
[layerArray removeAllObjects];
_cellWidth = _frameWidth / _gridSizeX;
_cellHeight = _frameHeight / _gridSizeY;
int firstCellY = _frameHeight - _cellHeight;
UIColor *strokeColor = [UIColor grid];
for(int x = 0; x < _gridSizeX; x++) {
for(int y = 0; y < _gridSizeY; y++) {
CellLayer *cellLayer = [CellLayer layer];
cellLayer.frame = CGRectMake(x * _cellWidth, firstCellY - (y * _cellHeight), _cellWidth, _cellHeight);
cellLayer.backgroundColor = [self getColourForState:mCells[x][y] andX:x andY:y].CGColor;
cellLayer.borderColor = strokeColor.CGColor;
cellLayer.borderWidth = 0.5;
cellLayer.col = x;
cellLayer.row = y;
cellLayer.state = mCells[x][y];
[layerArray addObject:cellLayer];
[self.layer addSublayer:cellLayer];
}
}
}
Then as advised here, following the touch events I only change the properties of cells which need to be updated:
- (void)redrawChangedCells
{
[CATransaction setDisableActions:YES];
[[layerArray copy] enumerateObjectsUsingBlock:^(CellLayer *layer, NSUInteger idx, BOOL *stop) {
if(mCells[layer.col][layer.row] != layer.state) {
layer.backgroundColor = [self getColourForState:mCells[layer.col][layer.row] andX:layer.col andY:layer.row].CGColor;
layer.state = mCells[layer.col][layer.row];
[self updateLayerArrayWithLayer:layer andIndex:idx];
}
}];
}