Lookslike drawRect本身(甚至是空的)会导致显着的性能瓶颈,具体取决于设备的分辨率 – 更大的屏幕是更糟糕的事情.
有没有办法加快重绘视图的内容?
更多细节:
我正在iOS上创建一个小型绘图应用程序 – 用户将手指移到显示器上以绘制线条.
这背后的想法非常简单 – 当用户移动他的手指触摸时,移动会将更改累积到屏幕外缓冲区图像中,并使视图无效以将屏幕外缓冲区与视图的内容合并.
简单的代码段可能如下所示:
@interface CanvasVIEw : UIVIEw...end;@implementation CanvasVIEw{ UIImage *canvasContentimage; UIImage *bufferImage CGContextRef drawingContext;}- (voID)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{ // prepare drawing to start UIGraphicsBeginImageContext(canvasSize); drawingContext = UIGraphicsGetCurrentContext(); ...}-(voID)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{ // draw to bufferImage CGContextMovetoPoint(drawingContext,prevPoint.x,prevPoint.y); CGContextAddlinetoPoint(drawingContext,point.x,point.y); CGContextstrokePath(drawingContext); ... [self setNeeddisplay];}-(voID) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{ //finish drawing UIGraphicsEndImageContext(); //merge canvasContentimage with bufferImage ...}-(voID)drawRect:(CGRect)rect{ // draw bufferImage - merge it with current vIEw's content CGContextRef context = UIGraphicsGetCurrentContext(); CGContextDrawImage(context,self.bounds,canvasContentimage.CGImage); CGContextDrawImage(context,imageRect,bufferImage.CGImage); ...}
我还实现了一个小助手类来计算fps率.
所以上面的方法在非视网膜屏幕上工作得相当好,产生接近60fps.然而fps率在视网膜屏幕上显着下降.例如在iPad Retina上它大约是15-20 fps,这太慢了.
我认为第一个明显的原因是setNeedsdisplay导致重绘整个屏幕,这是一个巨大的资源浪费.所以我转到setNeedsdisplayInRect只更新一个脏区域.令人惊讶的是,它没有改变任何关于性能的事情(至少根据测量和视觉上没有任何明显的变化).
所以我开始尝试不同的方法来找出瓶颈.当我评论出所有的绘图逻辑时,fps率仍然保持在15-20 – 看起来问题在于绘制逻辑之外.
最后,当我完全注释掉drawRect方法时,fps上升到60.不是说我只删除了实现,甚至是一个声明.不确定我的术语所以这里是结果:
// -(voID)drawRect:(CGRect)rect{// // draw bufferImage - merge it with current vIEw's content// ...// }
当我将所有绘图代码从drawRect方法移动到touchmoved方法时,更有趣的是它不会影响性能,但是相同数量的绘图/处理逻辑仍然与使用drawRect方法的版本相比 – 甚至每次都更新整个视图时间仍然给我60fps.
一个问题是没有drawRect我无法想象这些变化.
所以我来到了预生成的drawRect方法警告的内容:
“Only overrIDe drawRect: if you perform custom drawing. An empty
implementation adversely affects performance during animation.”
我的猜测是,每次触发自定义drawRect时,系统都会创建并销毁图形上下文,从而“严重影响性能”
所以问题是:
>有没有办法加速drawRect调用,比如让系统重用资源从调用drawRect调用什么?
>如果这是一个死胡同,还有哪些其他可用于更新视图内容的方法?目前还不能选择OpenGL,因为已经实现了很多代码/逻辑,并且需要花费很多精力才能移植它.
我很乐意提供所需的任何其他信息.
并提前感谢任何建议!
编辑:
经过一些调查和实验后,我开始使用UIImageVIEw及其image属性来动态更新视图的内容.它提供了小的性能改进(绘图在19-22 fps时更稳定).然而它仍然远远没有目标50-60fps.
有人认为我注意到只更新屏幕外缓冲区图像的脏部分确实有意义 – 不强制视图的内容更新,重绘屏幕外缓冲区的纯逻辑提供大约60 fps.
但是,一旦我试图将更新的图像附加到UIImageVIEw.image属性来更新它的内容,fps就会降到19-22.这是合理的,因为赋予属性强制整个图像在视图侧重绘.
所以问题仍然存在 – 是否有任何方法只更新显示内容的视图的指定部分(UIImageVIEw)?
解决方法 花了好几天后,我出乎意料(至少对我自己)的结果.我能够在视网膜iPad上达到30fps,这是现在可接受的结果.
对我有用的诀窍是:
>子类UIImageVIEw
>使用UIImageVIEw.image属性更新内容 – 与使用setNeedsdisplay / setNeedsdisplayInRect方法的普通UIVIEw相比,它提供了更好的结果.
>使用[self performSelector:@selector(setimage 总结
以上是内存溢出为你收集整理的ios – 在Retina显示器上使用drawRect / update图像性能问题的UIView全部内容,希望文章能够帮你解决ios – 在Retina显示器上使用drawRect / update图像性能问题的UIView所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)