Ios 如何提高drawRect的性能?

Ios 如何提高drawRect的性能?,ios,objective-c,drawing,drawrect,Ios,Objective C,Drawing,Drawrect,在我的应用程序中,我通过将UIView子类化来创建网格视图。如果用户触摸网格的一个单元格,它会在许多不同的状态之间切换,例如“开”或“关”,并相应地改变颜色。因此,当触摸单元格时,我会调用setNeedsDisplay刷新视图 在我的新iphone5s上效果很好,但在iphone4上性能很差——我的整个应用程序都冻结了,音频断断续续等。有更好的方法吗?如何提高性能 /** * Draw rect */ -(void)drawRect:(CGRect)rect { _cellWidt

在我的应用程序中,我通过将UIView子类化来创建网格视图。如果用户触摸网格的一个单元格,它会在许多不同的状态之间切换,例如“开”或“关”,并相应地改变颜色。因此,当触摸单元格时,我会调用
setNeedsDisplay
刷新视图

在我的新iphone5s上效果很好,但在iphone4上性能很差——我的整个应用程序都冻结了,音频断断续续等。有更好的方法吗?如何提高性能

 /**
 * Draw rect
 */
-(void)drawRect:(CGRect)rect
{
    _cellWidth = _frameWidth / _gridSizeX;
    _cellHeight = _frameHeight / _gridSizeY;

    int firstCellY = _frameHeight - _cellHeight;

    for(int x = 0; x < _gridSizeX; x++) {
        for(int y = 0; y < _gridSizeY; y++) {

            CGRect rect = CGRectMake(x * _cellWidth, firstCellY - (y * _cellHeight), _cellWidth, _cellHeight);

            UIColor *strokeColor = [UIColor grid];
            UIColor *fillColor;

            if(currentBeat != x) {
                switch(mCells[x][y]) {
                    case OFF:
                        //bar lines
                        if(x % 4 == 0) {
                            fillColor = [UIColor bgBar];
                        }
                        //octave lines
                        else if(scaleLength > 0 && (y % scaleLength == 0 || y == _gridSizeY-1)) {
                            fillColor = [UIColor bgOctave];
                        }
                        else {
                            fillColor = [UIColor bgMain];
                        }
                        break;
                    case ON:
                        fillColor = [UIColor cellOn];
                        break;
                    case ON_EXTEND:
                        fillColor = [UIColor cellOnExtend];
                        break;
                    case LOCKED:
                        fillColor = [UIColor cellLocked];
                        break;
                    case LOCKED_EXTEND:
                        fillColor = [UIColor cellLockedExtend];
                        break;
                    default:
                        break;
                }
            }
            else {
                switch (mCells[x][y]) {
                    case OFF:
                        if(_playing) {
                            fillColor = [UIColor bgMainHL];
                        }
                        else {
                            fillColor = [UIColor bgBar];
                        }
                        break;
                    case ON:
                        if(_playing) {
                            fillColor = [UIColor cellOnHL];
                        }
                        else {
                            fillColor = [UIColor cellOn];
                        }
                        break;
                    case ON_EXTEND:
                        fillColor = [UIColor cellOnExtendHL];
                        break;
                    case LOCKED:
                        if(_playing) {
                            fillColor = [UIColor cellLockedHL];
                        }
                        else {
                            fillColor = [UIColor cellLocked];
                        }
                        break;
                    case LOCKED_EXTEND:
                        fillColor = [UIColor cellLockedExtendHL];
                        break;
                    default:
                        break;
                }
            }

            CGContextRef context = UIGraphicsGetCurrentContext();
            CGContextSetFillColorWithColor(context, fillColor.CGColor);
            CGContextSetStrokeColorWithColor(context, strokeColor.CGColor);
            CGContextFillRect(context, rect);
            CGContextStrokeRect(context, rect);
        }
    }
}


/**
 * Touch events
 */
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    [self handleTouches:touches withEvent:event];
}
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
    [self handleTouches:touches withEvent:event];
}
-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
    [self handleTouches:touches withEvent:event];
}
-(void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
{
    [self handleTouches:touches withEvent:event];
}


/**
 * Handle touches
 */
-(void)handleTouches:(NSSet *)touches withEvent:(UIEvent *)event
{
    UITouch *touch = [[event allTouches] anyObject];
    CGPoint location = [touch locationInView:self];

    //Find column and row
    int col = (int) (location.x / _cellWidth);
    int row = (int) _gridSizeY - (location.y / _cellHeight);

    //Only redraw view when row and column changed, so doesn't redraw every touch that's registered
    if([touch phase] == UITouchPhaseBegan || (touchBeganCol != col || touchBeganRow != row)) {
        [self.delegate mViewTouchEventWithTouch:touch andRow:row andColumn:col];
        [self setNeedsDisplay];
        touchBeganCol = col;
        touchBeganRow = row;
        NSLog(@"redraw");
    }
    else if([touch phase] == UITouchPhaseEnded || [touch phase] == UITouchPhaseCancelled) {
        [self.delegate mViewTouchEventWithTouch:touch andRow:row andColumn:col];
        [self setNeedsDisplay];
        touchBeganCol = 99999;
        touchBeganRow = 99999;
        NSLog(@"redraw");
    }
}
/**
*绘制矩形
*/
-(void)drawRect:(CGRect)rect
{
_cellWidth=\u frameWidth/\u gridSizeX;
_cellHeight=\u frameHeight/\u gridSizeY;
int firstCellY=\u frameHeight-\u cellHeight;
对于(int x=0;x<\u gridSizeX;x++){
对于(int y=0;y<\u gridSizeY;y++){
CGRect rect=CGRectMake(x*_cellWidth,firstCellY-(y*_cellHeight),_cellWidth,_cellHeight);
UIColor*strokeColor=[UIColor网格];
UIColor*fillColor;
如果(当前拍数!=x){
开关(mCells[x][y]){
案例:
//条线
如果(x%4==0){
fillColor=[UIColor bgBar];
}
//倍频程线
else if(scaleLength>0&(y%scaleLength==0 | | y==U gridSizeY-1)){
fillColor=[UIColor bg倍频程];
}
否则{
fillColor=[UIColor bgMain];
}
打破
案件涉及:
fillColor=[UIColor-cellOn];
打破
(扩展)个案:
fillColor=[UIColor cellOnExtend];
打破
案件锁定:
fillColor=[UIColor cellLocked];
打破
案例锁定\u扩展:
fillColor=[UIColor cellLockedExtend];
打破
违约:
打破
}
}
否则{
开关(mCells[x][y]){
案例:
如果(正在播放){
fillColor=[UIColor bgMainHL];
}
否则{
fillColor=[UIColor bgBar];
}
打破
案件涉及:
如果(正在播放){
fillColor=[UIColor cellOnHL];
}
否则{
fillColor=[UIColor-cellOn];
}
打破
(扩展)个案:
fillColor=[UIColor cellOnExtendHL];
打破
案件锁定:
如果(正在播放){
fillColor=[UIColor cellLockedHL];
}
否则{
fillColor=[UIColor cellLocked];
}
打破
案例锁定\u扩展:
fillColor=[UIColor cellLockedExtendHL];
打破
违约:
打破
}
}
CGContextRef context=UIGraphicsGetCurrentContext();
CGContextSetFillColorWithColor(上下文,fillColor.CGColor);
CGContextSetStrokeColorWithColor(上下文,strokeColor.CGColor);
CGContextFillRect(上下文,rect);
CGContextStrokeRect(上下文,rect);
}
}
}
/**
*触摸事件
*/
-(无效)触摸开始:(NSSet*)触摸事件:(UIEvent*)事件
{
[自行触摸:触摸事件:事件];
}
-(无效)触摸移动:(NSSet*)触摸事件:(UIEvent*)事件
{
[自行触摸:触摸事件:事件];
}
-(void)touchesend:(NSSet*)toucheevent:(UIEvent*)event
{
[自行触摸:触摸事件:事件];
}
-(无效)触控取消:(NSSet*)触控事件:(UIEvent*)事件
{
[自行触摸:触摸事件:事件];
}
/**
*把手接触
*/
-(无效)手触:(NSSet*)接触事件:(UIEvent*)事件
{
UITouch*touch=[[event AllTouchs]anyObject];
CGPoint位置=[触摸位置查看:自];
//查找列和行
int col=(int)(location.x/_cellWidth);
int row=(int)_gridSizeY-(location.y/_cellHeight);
//只有在行和列发生更改时才重新绘制视图,因此不会重新绘制已注册的每个触摸
如果([touch phase]==UITouchPhaseBegan | | |(touchBeganCol!=col | | | touchBeganRow!=row)){
[self.delegate mViewTouchEventWithTouch:touch andRow:row:row和coln:col];
[自我设置需要显示];
touchBeganCol=col;
touchBeganRow=行;
NSLog(“重新绘制”);
}
否则如果([触摸阶段]==UITouchPhase已取消| |[触摸阶段]==UITouchPhase已取消){
[self.delegate mViewTouchEventWithTouch:touch andRow:row:row和coln:col];
[自我设置需要显示];
touchBeganCol=99999;
touchBeganRow=99999;
NSLog(“重新绘制”);
}
}

有几件事可以帮上忙:
根据经验,您应该尽量避免在图形代码中进行对象分配,因为这非常昂贵。在代码中,下一行可以移到double for循环之外,只需重用变量即可

       UIColor *strokeColor = [UIColor grid];
       UIColor *fillColor;
为了扩展前面的注释,这是我不确定的,甚至像[UIColor bgBar]这样的调用也可能实例化对象。我通常有类变量,比如bgBarColor,已经设置了合适的颜色

另一个有用的提示是使需要为红色的rect无效
/**
 * 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];
        }
    }
}
- (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];
        }
    }];
}