iOS 提高绘制性能的"脏矩形"

2019-09-15  本文已影响0人  王技术

需求大概是这样 :

记录手指在屏幕上划过的点, 在点上绘制指定图案.

思路大概是这样 :

touchesBegantouchesMoved 记录手指划过的点, 每增加一个点调用 setNeedsDisplaydrawRect 中重绘页面

代码肥肠的简单 :

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    CGPoint point = [[touches anyObject] locationInView:self];
    [self addBrushStrokeAtPoint:point];
}

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
    CGPoint point = [[touches anyObject] locationInView:self];
    [self addBrushStrokeAtPoint:point];
}
- (void)addBrushStrokeAtPoint:(CGPoint)point {
    [self.strokes addObject:[NSValue valueWithCGPoint:point]];
    [self setNeedsDisplay];
}

- (void)drawRect:(CGRect)rect {
    for (NSValue *value in self.strokes) {
        CGPoint point = [value CGPointValue];
        CGRect brushRect = CGRectMake(point.x - BRUSH_SIZE/2, point.y - BRUSH_SIZE/2, BRUSH_SIZE, BRUSH_SIZE);
        [[UIImage imageNamed:@"star"] drawInRect:brushRect];
    }
}

但是!
这样好像内存和 CPU 都会吃不消 :


这还是在模拟器上, 感觉就快扛不住了, 要是在真机上就更难了
问题就在于手指每移动一点我们就会重绘之前所有的路径
但是大部分场景并没有改变, 做了很多无用功
我们绘制地越多,就会越慢。随着时间的增加每次重绘需要更多的时间,屏幕帧数也会下降

为了减少不必要的绘制, iOS 设备把屏幕分为需要重绘的区域和不需要重绘的区域
那些需要重绘的区域被称为脏区域
但是在实际应用中, 区域的形状复杂, 通常会用包含指定区域的矩形来表示需要绘制区域
这个位置就是脏矩形
当检测到指定视图或图层的某个部分需要被重绘,可以直接调用 -setNeedsDisplayInRect: 来标记它
这样就会在一次视图刷新时调用视图的 -drawRect:(或图层代理的 -drawLayer:inContext: 方法)重绘时
就只重绘我们标记的区域了

于是我们把代码改成这个样子

#define BRUSH_SIZE 32

- (void)addBrushStrokeAtPoint:(CGPoint)point {
    [self.strokes addObject:[NSValue valueWithCGPoint:point]];
    [self setNeedsDisplayInRect:[self brushRectForPoint:point]];
}

- (CGRect)brushRectForPoint:(CGPoint)point {
    return CGRectMake(point.x - BRUSH_SIZE/2, point.y - BRUSH_SIZE/2, BRUSH_SIZE, BRUSH_SIZE);
}

- (void)drawRect:(CGRect)rect {
    for (NSValue *value in self.strokes) {
        CGPoint point = [value CGPointValue];
        CGRect brushRect = [self brushRectForPoint:point];
        if (CGRectIntersectsRect(rect, brushRect)) {
            [[UIImage imageNamed:@"star"] drawInRect:brushRect];
        }
    }
}

修改过后的性能还是很客观的


本文代码

上一篇 下一篇

猜你喜欢

热点阅读