【发布时间】:2012-05-07 14:56:41
【问题描述】:
我正在开发一个使用 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)];
}
将此添加到 MyView(我的自定义视图):
- (void)drawRect:(CGRect)rect
{
// Just log what is being updated
NSLog(@"%@", NSStringFromCGRect(rect));
}
就是这样。如果我在第三十台 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}}
此外,如果我停止移动超过 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}}
【问题讨论】:
-
在我的例子中,当在 setNeedsDisplayInRect 第一次之后调用 drawRect 时,矩形是完整的边界(不要问我为什么),任何下一次调用它正是我的矩形在 setNeedsDisplayInRect 中指定为参数。您是否多次测试过触摸动作?
-
它主要发生在设备上。但是,如果您四处移动手指,然后等待大约 10 或 15 秒,然后再次触摸并移动,您可以在模拟器上实现它。在 iPad3 设备上,即使手指移动也会发生这种情况。太烦人了:)
-
我不久前发布了@这个(stackoverflow.com/questions/9299018/…)。这似乎只是第一次通话。我从来没有找到原因/修复,只是继续前进,因为我不需要那种级别的性能优化。您可以测试 rect == 视图大小而不是绘制吗?也许不是一个选择。
-
我尝试测试 rect,但不幸的是,如果我退出 drawRect 方法而不绘制 rect 覆盖的内容,则视图最终为空,因为调用 drawRect 会自动清除视图。这太令人沮丧了,听起来很简单。
-
奇怪的问题。您是否考虑过通过将每个绘图动作放到它自己的视图或图层中来解决它,然后只是将它们堆叠在一起?这样,您只会“弄脏”并且每次都必须重新绘制一个新图层,并且您将利用合成引擎来处理需要更新哪些其他图层。如果您尝试这样做,请告诉我们它是否能提供更好的性能。
标签: ios core-animation core-graphics