UIGraphicsGetCurrentContext()寿命短

我有一个实现徒手绘制的视图,但是我有一个小问题。 我注意到在iPad 3上,所有的东西都变成了地狱,所以我试图更新我的绘图代码(可能是我应该做的第一个地方),只更新被抚摸的部分。 然而,打开后的第一次冲程,以及闲置约10秒后的第一次冲程非常缓慢。 在所有事情都“热身”之后,它就像黄油一样平滑,每个drawRect只需要大约0.15ms。 我不知道为什么,但整个视图矩形被标记为第一个drawRect脏,第一个drawRect后空闲(然后它需要约150毫秒更新)。 堆栈跟踪显示我的矩形被CABackingStoreUpdate_覆盖

如果矩形很大,我试图不绘制图层,但是随后我的整个上下文变为空白(当我在旧区域上绘制像乐透彩票票时,会再次出现)。 有没有人有任何想法与UIGraphicsGetCurrentContext()? 这是我能想象到的唯一的麻烦。 也就是说,我的观点背景被上下文精灵拉下来了,所以需要重新充实自己。 有什么设置我可以用来坚持相同的上下文吗? 或者还有其他的东西在这里…在初始显示之后没有必要更新完整的矩形。

我的drawRect非常简单:

 - (void)drawRect:(CGRect)rect { CGContextRef c = mDrawingLayer ? CGLayerGetContext(mDrawingLayer) : NULL; if(!mDrawingLayer) { c = UIGraphicsGetCurrentContext(); mDrawingLayer = CGLayerCreateWithContext(c, self.bounds.size, NULL); c = CGLayerGetContext(mDrawingLayer); CGContextSetAllowsAntialiasing(c, true); CGContextSetShouldAntialias(c, true); CGContextSetLineCap(c, kCGLineCapRound); CGContextSetLineJoin(c, kCGLineJoinRound); } if(mClearFlag) { CGContextClearRect(c, self.bounds); mClearFlag = NO; } CGContextStrokePath(c); CFAbsoluteTime startTime = CFAbsoluteTimeGetCurrent(); CGContextDrawLayerInRect(UIGraphicsGetCurrentContext(), self.bounds, mDrawingLayer); NSLog(@"%.2fms : %fx %f", (CFAbsoluteTimeGetCurrent() - startTime)*1000.f, rect.size.width, rect.size.height); } 

我在Apple Dev论坛上发现了一个有用的线索来描述这个确切的问题。 它只存在于iOS 5.0之后,理论上是因为Apple引入了一个双缓冲系统,所以前两个drawRects总是会满的。 然而,没有解释为什么闲置后会再次发生。 理论上说,底层的缓冲区不是由GPU保证的,而且会随时丢弃,需要重新创build。 解决scheme(直到苹果发布某种真正的解决scheme)是ping缓冲区,以便它不会被释放:

 mDisplayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(pingRect)]; [mDisplayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; - (void)pingRect { //Already drawing if(mTouchCount > 0) return; //Even touching just one pixel will keep the buffer alive [self setNeedsDisplayInRect:CGRectMake(0, 0, 1, 1)]; } 

唯一的弱点是如果用户将手指完全保持5秒以上,但我认为这是一个可以接受的风险。

编辑有趣的更新。 事实certificate,调用setNeedsDisplay就足以使缓冲区保持活动状态,即使它立即返回。 所以我将其添加到我的drawRect方法中:

 - (void)drawRect:(CGRect)rect { if(rect.size.width == 1.f) return; //... } 

希望能够抑制这种刷新方式必然会增加的用电量。