我设法解决了这个问题:
我创建了一个新的 UIView 子类头和实现文件:
@interface fingerView : UIView {
}
然后在我的主视图中,在标题中我声明了其中的 5 个视图:
fingerView* fview[5];
在我的主视图实现中,我创建了这个实例的 5 个视图,每个手指分别一个。此外,必须确保制作它们,为它们中的每一个启用多点触控,并确保 clearsContextBeforeDrawing 设置为 NO,因为我们将一次更新它们中的小矩形,并且我们不希望系统清除我们的工作。
for(int i=0;i<5;i++) {
fview[i] = [[pView alloc] initWithFrame:topFrame];
[self addSubview: fview[i]];
[self sendSubviewToBack: fview[i]];
fview[i].opaque= NO;
fview[i].clearsContextBeforeDrawing = NO;
fview[i].multipleTouchEnabled = YES;
}
现在在每个手指视图中保留一个大数组(我使用一个简单的数组,比如 10,000 长),其中包含手指绘制的 x 和 y 位置。每当手指移动时,主视图都会检测到它,并调用 [fview[i] updatePos(newx, newy)],至关重要的是,我们将命令视图仅在这些坐标周围更新其自身的一小部分:
[fview[i] setNeedsDisplayInRect: fingerRect];
其中 fingerRect 是一个以 (newx, newy) 为中心的小矩形。在每个手指视图的 drawRect 方法中,
- (void)drawRect:(CGRect)rect
{
if (movep==0) return;
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetRGBStrokeColor(context, r, g, b, 1);
CGContextSetLineWidth(context, linewidth);
//paint finger
CGContextBeginPath(context);
CGFloat slack= 15;
CGFloat minx= CGRectGetMinX(rect)-slack;
CGFloat maxx= CGRectGetMaxX(rect)+slack;
CGFloat miny= CGRectGetMinY(rect)-slack;
CGFloat maxy= CGRectGetMaxY(rect)+slack;
bool drawing = NO;
for(int i=0;i<movep;i++) {
CGFloat xx= x[i];
CGFloat yy= y[i];
if(xx>minx && xx<maxx && yy>miny && yy<maxy) {
if(drawing) {
// continue line
CGContextAddLineToPoint(context, xx, yy);
CGContextMoveToPoint(context, xx, yy);
} else {
// start drawing
CGContextMoveToPoint(context, xx, yy);
drawing= YES;
}
} else {
drawing= NO;
}
}
CGContextStrokePath(context);
而且,正如我提到的
- (void)updatePos: (CGFloat)xnew: (CGFloat) ynew
{
x[movep]= xnew;
y[movep]= ynew;
movep= movep+1;
希望你能弄清楚这是如何工作的。每个视图都会查看这个已修改的矩形,并检查围绕该矩形的所有手指位置,并且只绘制那些。这将归结为很少的笔画,因此整个代码运行得非常快。
整体的教训是 UIViews 是非常优化的。尽可能地尝试制作一大堆,如果有的话,只在本地更新它们,然后让 Apple 的魔法将它们融合在一起。