编辑:更多的细节可能是有用的:这是一个二维拼图/街机游戏,玩家移动石块以匹配它们.根本没有3D渲染.绘图已经太慢,甚至还没有得到碎片的爆炸.还有一个级别淡入淡出,非常关心.但是到目前为止,这一切都在模拟器上.我还没有一个实际的iPhone来测试,我敢打赌实际的设备将至少要快一点.
我有自己的Draw2D类,它是一种类型的UIView,设置在this tutorial.我有一个NSTimer,它在Draw2D中启动以下链接调用:
[setNeedsDisplay]; //调用drawRect,它是Draw2D的主绘图函数
drawRect(rect: CGRect) { scr_step(); // the master update function,which loops thru all objects and calls their individual update functions. I put it here so that updating and drawing are always in sync CNT = UIGraphicsGetCurrentContext(); // get the curret drawing context switch (Realm) // based on what realm im in,call the draw function for that realm { case rlm.intro: scr_draw_intro(); case rlm.mm: scr_draw_mm(); case rlm.level: scr_draw_level(); // this in particular loops thru all objects and calls their individual draw functions default: return; } var i = AARR.count - 1; // loop thru my own animation objects and draw them too,note it's iterating backwards because sometimes they destroy themselves while (i >= 0) { let A = AARR[i]; A.scr_draw(); i -= 1; } }
所有的绘图工作正常,但缓慢.
现在我想要优化绘图的问题.我只想画在需要绘图的脏矩形,而不是整个屏幕,这是setNeedsDisplay正在做什么.
我找不到任何教程或良好的示例代码.我发现最接近的是苹果的文档here,但是除了别的以外,它不能解释到目前为止所有脏矩形列表.它还没有明确说明在每次调用drawRect结束时是否自动清除脏矩形列表?
它也不解释我是否必须手动剪辑基于矩形的所有绘图.我在网络上发现了相互冲突的信息,显然不同的iOS版本做的不同.特别是,如果我要hafta手动剪辑的东西,那么我没有看到苹果的核心功能的第一位.我可以保持自己的矩形列表,并手动将每个绘图目标矩形与脏矩形进行比较,看看是否应该绘制任何东西.那会是一个巨大的痛苦,但是,因为我有一个背景图片在每一个级别,我会hafta在每个移动物体后面绘制一块.我真正希望的是使用setNeedsDisplayInRect的正确方法,让核心框架对于在下一个绘制循环中绘制的所有内容进行自动剪裁,以便它自动仅绘制背景的一部分以及顶部的移动对象.
所以我尝试了一些实验:首先在我的石头阵列:
func scr_draw_stone() { // the following 3 lines are new,I added them to try to draw in only dirty rectangles if (xvp != xv || yvp != yv) // if the stone's coordinates have changed from its prevIoUs coordinates { MyD.setNeedsDisplayInRect(CGRectMake(x,y,MyD.swc,MyD.shc)); // MyD.swc is Draw2D's current square width in points,maintained to softcode things for different screen sizes. } MyD.img_stone?.drawInRect(CGRectMake(x,MyD.shc)); // draw the plain stone img?.drawInRect(CGRectMake(x,MyD.shc)); // draw the stone's icon }
这似乎没有什么改变.事情正像以前一样缓慢.那么我把它放在括号中:
[MyD.setNeedsDisplayInRect(CGRectMake(x,MyD.shc))];
我不知道括号是什么,但是我的原始setNeedsDisplay在括号中就像他们在教程中所说的那样.所以我在我的石头对象中尝试过,但是也没有效果.
那么我需要做什么来使setNeedsDisplayInRect正常工作?
现在,我怀疑我的主绘画功能需要一些条件检查,如:
if (ListOfDirtyRectangles.count == 0) { [setNeedsDisplay]; // just redraw the whole view } else { [setNeedsDisplayInRect(ListOfDirtyRecangles)]; }
但是我不知道内置的脏矩形列表的名称.我发现this说方法名称是getRectsBeingDrawn,但这是Mac OSX.它在iOS中不存在.
谁能帮我吗?我正在跟踪吗?我还是相当新的Mac和iOS.
解决方法
如果你有一个背景和其他对象,你应该为这些使用单独的视图或图层,而不是重绘.
您还可以考虑使用SpriteKit,SceneKit,OpenGL ES等技术.
除此之外,我不太清楚我明白你的问题.当您调用setNeedsDisplayInRect时,它会将该rect添加到那些需要重新绘制的位置(可能与已经在列表中的矩形合并). drawRect:稍后将被调用一次绘制一个矩形.
setNeedsDisplayInRect / drawRect:separation的全部要点是确保重绘一个给定部分视图的多个请求被合并在一起,而绘图只能在每个重绘周期进行一次.
您不应该在drawRect:中调用您的scr_step方法,因为它可能会在循环重绘循环中多次调用.这在iOS的“查看编程指南”(我的重点)中已经明确说明了:
The implementation of your drawRect: method should do exactly one
thing: draw your content. This method is not the place to be updating
your application’s data structures or performing any tasks not related
to drawing. It should configure the drawing environment,draw your
content,and exit as quickly as possible. And if your drawRect: method
might be called frequently,you should do everything you can to
optimize your drawing code and draw as little as possible each time
the method is called.
关于剪切,drawRect的文档规定:
You should limit any drawing to the rectangle specified in the rect
parameter. In addition,if the opaque property of your view is set to
YES,your drawRect: method must totally fill the specified rectangle
with opaque content.
没有任何想法你的观点显示,你所说的各种方法,什么实际需要时间,很难提供更多的洞察力你可以做什么.为您的实际需求提供更多细节,我们也许可以帮助.