setNeedsDisplayInRect:导致整个视图更新

mpr*_*vat 10 core-animation core-graphics ios

我正在开发一个使用CoreGraphics进行渲染的绘画应用程序.我的问题是,对于性能,我试图将更新限制为仅更改的视图的某些部分.为此,我使用setNeedsDisplayInRect:,但有时视图会更新其整个内容,从而导致口吃.这在第3代iPad上尤其明显,但在模拟器和iPad2中也会出现较小程度的问题.我试图删除此行为.

为了展示这个问题,我使用Xcode中的模板创建了一个简单的"单视图"项目.创建了一个自定义UIView子类,我将其设置为xib文件中的视图控制器视图.

将此添加到UIViewController:

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
    // Asks that the view refreshes a smal rectangle
    [self.view setNeedsDisplayInRect:CGRectMake(10, 10, 20, 20)];
}
Run Code Online (Sandbox Code Playgroud)

将其添加到MyView(我的自定义视图):

- (void)drawRect:(CGRect)rect
{
    // Just log what is being updated
    NSLog(@"%@", NSStringFromCGRect(rect));
}
Run Code Online (Sandbox Code Playgroud)

就是这样.如果我在第3台iPad(实际设备)上运行该应用程序,日志会显示该视图在其内容中不时重新绘制(非常频繁).这太令人沮丧了,我没有想法

更新:这是一些日志.它肯定会显示有时更新的完整视图.我试图让它完全停止,但无法想象如何...

2012-05-04 08:34:01.851 TestUpdateArea[45745:707] {{0, 0}, {320, 460}}
2012-05-04 08:34:30.184 TestUpdateArea[45745:707] {{0, 0}, {320, 460}}
2012-05-04 08:34:30.197 TestUpdateArea[45745:707] {{0, 0}, {320, 460}}
2012-05-04 08:34:30.215 TestUpdateArea[45745:707] {{10, 10}, {20, 20}}
2012-05-04 08:34:30.226 TestUpdateArea[45745:707] {{10, 10}, {20, 20}}
2012-05-04 08:34:30.242 TestUpdateArea[45745:707] {{10, 10}, {20, 20}}
2012-05-04 08:34:30.258 TestUpdateArea[45745:707] {{10, 10}, {20, 20}}
2012-05-04 08:34:30.274 TestUpdateArea[45745:707] {{10, 10}, {20, 20}}
2012-05-04 08:34:30.290 TestUpdateArea[45745:707] {{10, 10}, {20, 20}}
2012-05-04 08:34:30.306 TestUpdateArea[45745:707] {{10, 10}, {20, 20}}
2012-05-04 08:34:30.322 TestUpdateArea[45745:707] {{10, 10}, {20, 20}}
2012-05-04 08:34:30.338 TestUpdateArea[45745:707] {{10, 10}, {20, 20}}
2012-05-04 08:34:30.354 TestUpdateArea[45745:707] {{10, 10}, {20, 20}}
2012-05-04 08:34:30.371 TestUpdateArea[45745:707] {{10, 10}, {20, 20}}
2012-05-04 08:34:30.387 TestUpdateArea[45745:707] {{10, 10}, {20, 20}}
2012-05-04 08:34:30.403 TestUpdateArea[45745:707] {{10, 10}, {20, 20}}
2012-05-04 08:34:30.419 TestUpdateArea[45745:707] {{10, 10}, {20, 20}}
2012-05-04 08:34:30.439 TestUpdateArea[45745:707] {{0, 0}, {320, 460}}
2012-05-04 08:34:30.457 TestUpdateArea[45745:707] {{10, 10}, {20, 20}}
Run Code Online (Sandbox Code Playgroud)

此外,如果我停止移动超过10秒左右并恢复,它肯定会非常一致:

2012-05-04 08:34:33.305 TestUpdateArea[45745:707] {{10, 10}, {20, 20}}
2012-05-04 08:34:33.321 TestUpdateArea[45745:707] {{10, 10}, {20, 20}}
2012-05-04 08:35:00.202 TestUpdateArea[45745:707] {{0, 0}, {320, 460}}
2012-05-04 08:35:00.221 TestUpdateArea[45745:707] {{0, 0}, {320, 460}}
2012-05-04 08:35:00.234 TestUpdateArea[45745:707] {{0, 0}, {320, 460}}
2012-05-04 08:35:00.251 TestUpdateArea[45745:707] {{10, 10}, {20, 20}}
Run Code Online (Sandbox Code Playgroud)

Nic*_*ood 13

接受的答案是错误的(或至少是误导性的).

这是setNeedsDisplayInRect的一个简单代码示例:按宣传的方式工作:

http://charcoaldesign.co.uk/resources/chalkboard.zip

我怀疑Apple文档试图解释这样一个事实:在iOS上,每个视图支持图像都转换为OpenGL纹理,并且每个帧都重新合成整个屏幕.这与您的代码是否必须清除和重绘视图的支持纹理的全部内容的问题不同.

通过使用setNeedsDisplayInRect:您可以避免昂贵的重绘内容,这些内容在帧之间不会更改(使用核心图形而不是硬件加速).无论如何,整个屏幕仍然会被重绘,但这并不重要,因为GPU的硬件加速,与drawRect中的代码不同:


Mal*_*ndi 5

检查这个苹果文档

他们说 :

因为iPhone/iPod touch/iPad更新其屏幕的方式,如果你打电话-setNeedsDisplayInRect:或是 ,整个视图将被重绘-setNeedsDisplay:.

每个UIView都被视为一个单独的元素.当您通过调用-setNeedsDisplayInRect:或部分或全部请求重绘时,-setNeedsDisplay:整个视图将被标记为更新.

所以我认为你需要使用子视图来更新整个View的独立矩形.