ios – 在Retina显示器上使用drawRectupdate图像性能问题的UIView

ios – 在Retina显示器上使用drawRectupdate图像性能问题的UIView,第1张

概述问题简而言之: LooksLike drawRect本身(甚至是空的)会导致显着的性能瓶颈,具体取决于设备的分辨率 – 更大的屏幕是更糟糕的事情. 有没有办法加快重绘视图的内容? 更多细节: 我正在iOS上创建一个小型绘图应用程序 – 用户将手指移到显示器上以绘制线条. 这背后的想法非常简单 – 当用户移动他的手指触摸时,移动会将更改累积到屏幕外缓冲区图像中,并使视图无效以将屏幕外缓冲区与视图的内 问题简而言之:

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所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1024612.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-23
下一篇 2022-05-23

发表评论

登录后才能评论

评论列表(0条)

保存