• 注册
当前位置:1313e > 默认分类 >正文

app优化篇

UIImageView高效加个圆角

一般通过clipsToBounds和layer.cornerRadius会强制Core Animation提前渲染屏幕的离屏绘制,影响性能。

通过贝塞尔曲线切割图片实现path.addclip();

drawRect在以下情况下会被调用:

 

1、如果在UIView初始化时没有设置rect大小,将直接导致drawRect不被自动调用。drawRect 掉用是在Controller->loadView, Controller->viewDidLoad 两方法之后掉用的.所以不用担心在 控制器中,这些View的drawRect就开始画了.这样可以在控制器中设置一些值给View(如果这些View draw的时候需要用到某些变量 值).
2、该方法在调用sizeToFit后被调用,所以可以先调用sizeToFit计算出size。然后系统自动调用drawRect:方法。
3、通过设置contentMode属性值为UIViewContentModeRedraw。那么将在每次设置或更改frame的时候自动调用drawRect:。
4、直接调用setNeedsDisplay

drawRect方法使用注意点:

1、 drawRect:方法不能手动显示调用,必须通过调用setNeedsDisplay 或 者 setNeedsDisplayInRect,让系统自动调该方法。
2、若使用calayer绘图,只能在drawInContext: 中(类似于drawRect)绘制,或者在delegate中的相应方法绘制。同样也是调用setNeedDisplay等间接调用以上方法
3、若要实时画图,不能使用gestureRecognizer,只能使用touchbegan等方法来调用setNeedsDisplay实时刷新屏幕
layoutSubviews在以下情况下会被调用:
1、init初始化不会触发layoutSubviews。
2、addSubview会触发layoutSubviews。
3、设置view的Frame会触发layoutSubviews,当然前提是frame的值设置前后发生了变化。
4、滚动一个UIScrollView会触发layoutSubviews。
5、旋转Screen会触发父UIView上的layoutSubviews事件。
6、改变一个UIView大小的时候也会触发父UIView上的layoutSubviews事件。
7、直接调用setLayoutSubviews。
tableview优化部分:
1、cell复用
2、在willDisplayCell方法中绑定数据。
3、cell高度的计算   
  定高的cell,tableView.rowHeight   
  动态高度的cell,对于已经计算出的高度,我们需要进行缓存
  self-sizing cell的概念,指定TableView的estimatedRowHeight属性的默认值。指定TableView的rowHeight属性为UITableViewAutomaticDimension。
4、渲染
  当有图像时,预渲染图像,在bitmap context先将其画一遍,导出成UIImage对象,然后再绘制到屏幕,这会大大提高渲染速度。
  渲染最好时的操作之一就是混合(blending)了,所以我们不要使用透明背景,将cell的opaque值设为Yes,背景色不要使用clearColor,尽量不要使用阴影渐变等

      使用透明view会引起blending,在iOS的图形处理中,blending主要指的是混合像素颜色的计算。最直观的例子就是,我们把两个图层叠加在一起,如果第一个图层的透明的,则最终像素的颜色计算需要将第二个图层也考虑进来。这一过程即为Blending。

 

5、减少视图的数目
  默认的UITableViewCell并且在它的ContentView上面添加控件时会相当消耗性能。所以目前最佳的方法还是继承UITableViewCell,并重写drawRect方法。
6、不要给cell动态添加subView
  在初始化cell的时候就将所有需要展示的添加完毕,然后根据需要来设置hide属性显示和隐藏。
7、异步化UI,不要阻塞主线程

8、离屏渲染的问题:

 

在VSync信号到来后,系统图形服务会通过CADisplayLink等机制通知App,App主线程开始在CPU中计算显示内容,比如视图的创建、布局计算、图片解码、文本绘制等。随后CPU会将计算好的内容提交到GPU去,由GPU进行变换、合成、渲染。随后GPU会把渲染结果提交到帧缓冲区去,等待下一次VSync信号到来时显示到屏幕上。由于垂直同步的机制,如果在一个VSync时间内,CPU或者GPU没有完成内容提交,则那一帧就会被丢弃,等待下一次机会再显示,而这时显示屏会保留之前的内容不变。这就是界面卡顿的原因。

在开发中,CPU和GPU中任何一个压力过大,都会导致掉帧现象,所以在开发时,也需要分别对CPU和GPU压力进行评估和优化。

 

CPU

加载资源,对象创建,对象调整,对象销毁,布局计算,Autolayout,文本计算,文本渲染,图片的解码, 图像的绘制(Core Graphics)都是在CPU上面进行的。

GPU

GPU是一个专门为图形高并发计算而量身定做的处理单元,比CPU使用更少的电来完成工作并且GPU的浮点计算能力要超出CPU很多。

GPU的渲染性能要比CPU高效很多,同时对系统的负载和消耗也更低一些,所以在开发中,我们应该尽量让CPU负责主线程的UI调动,把图形显示相关的工作交给GPU来处理,当涉及到光栅化等一些工作时,CPU也会参与进来,这点在后面再详细描述。

相对于CPU来说,GPU能干的事情比较单一:接收提交的纹理(Texture)和顶点描述(三角形),应用变换(transform)、混合(合成)并渲染,然后输出到屏幕上。通常你所能看到的内容,主要也就是纹理(图片)和形状(三角模拟的矢量图形)两类。

 

异步渲染

在子线程绘制,主线程渲染。例如 VVeboTableViewDemo

 

按需加载

  • 局部刷新,刷新一个cell就能解决的,坚决不刷新整个section或者整个tableView,刷新最小单元元素。

  • 利用runloop提高滑动流畅性,在滑动停止的时候再加载内容,像那种一闪而过的(快速滑动),就没有必要加载,可以使用默认的占位符填充内容。

     

当你使用UIImageView在加载一个视图的时候,这个视图虽然依然有CALayer,但是却没有申请到一个后备的存储,取而代之的是使用一个使用屏幕外渲染,将CGImageRef作为内容,并用渲染服务将图片数据绘制到帧的缓冲区,就是显示到屏幕上,当我们滚动视图的时候,这个视图将会重新加载,浪费性能。所以对于使用-drawRect:方法,更倾向于使用CALayer来绘制图层。因为使用CALayer的-drawInContext:,Core Animation将会为这个图层申请一个后备存储,用来保存那些方法绘制进来的位图。那些方法内的代码将会运行在CPU上,结果将会被上传到GPU。这样做的性能更为好些。

静态界面建议使用-drawRect:的方式,动态页面不建议。

离屏渲染的优化建议

  • 使用ShadowPath指定layer阴影效果路径。

  • 使用异步进行layer渲染(Facebook开源的异步绘制框架AsyncDisplayKit)。

  • 设置layer的opaque值为YES,减少复杂图层合成。

  • 尽量使用不包含透明(alpha)通道的图片资源。

  • 尽量设置layer的大小值为整形值。

  • 直接让美工把图片切成圆角进行显示,这是效率最高的一种方案。

  • 很多情况下用户上传图片进行显示,可以在客户端处理圆角。

  • 使用代码手动生成圆角image设置到要显示的View上,利用UIBezierPath(Core Graphics框架)画出来圆角图片。

  不可为:

  • 为图层设置遮罩(layer.mask)
  • 将图层的layer.masksToBounds / view.clipsToBounds属性设置为true
  • 将图层layer.allowsGroupOpacity属性设置为YES和layer.opacity小于1.0
  • 为图层设置阴影(layer.shadow *)。

  可为

  • 使用CAShapeLayer和UIBezierPath设置圆角
  • 通过设置shadowPath来优化性能,能大幅提高性能。
  • 当我们需要圆角效果时,可以使用一张中间透明图片蒙上去
  • 使用异步进行layer渲染(Facebook开源的异步绘制框架AsyncDisplayKit)
  • 设置layer的opaque值为YES,减少复杂图层合成
  • 设置layer的opaque值为YES,减少复杂图层合成
  • 尽量设置layer的大小值为整形值

那哪些情况会Offscreen Render呢?

1) drawRect
2) layer.shouldRasterize = true;
3) 有mask或者是阴影(layer.masksToBounds, layer.shadow*);3.1) shouldRasterize(光栅化)3.2) masks(遮罩)3.3) shadows(阴影)3.4) edge antialiasing(抗锯齿)3.5) group opacity(不透明)
4) Text(UILabel, CATextLayer, Core Text, etc)...

注:layer.cornerRadius,layer.borderWidth,layer.borderColor并不会Offscreen Render,因为这些不需要加入Mask。

一方面来说,一部分(通过drawRect并且使用任何CoreGraphics来实现的绘制,或使用CoreText[其实就是使用CoreGraphics]绘制)的确涉及到了“离屏绘制”,但是这和我们通常说的那种离屏绘制是有区别的。当你实现drawRect方法或者通过CoeGraphics绘制的时候,其实你是在使用CPU绘制。并且这个绘制的过程会在你的App内同步地进行。基本上你只是调用了一些向位图缓存内写入一些二进制信息的方法而已。

而另外一种形式离屏绘制是发生在绘制服务(是独立的处理过程)并且同时通过GPU执行(这里就不是像前面提到的用CPU了)。当OpengGL的绘制程序在绘制每个layer的时候,有可能因为包含多子层级关系而必须停下来把他们合成到一个单独的缓存里。你可能认为GPU应该总是比CPU牛逼一点,但是在这里我们还是需要慎重的考虑一下。因为对GPU来说,从当前屏幕(on-screen)到离屏(off-screen)上下文环境的来回切换(这个过程必须flush管线和光栅),代价是非常大的。因此对一些简单的绘制过程来说,这个过程有可能用CoreGraphics,全部用CPU来完成反而会比GPU做得更好。所以如果你正在尝试处理一些复杂的层级,并且在犹豫到底用-[CALayer setShouldRasterize:]还是通过CoreGraphics来绘制层级上的所有内容,唯一的方法就是测试并且进行权衡。

 

测试工具:
  • Core Animation,Instruments里的图形性能问题的测试工具。

  • view debugging,Xcode 自带的,视图层级。

  • reveal,视图层级。

app着重优化点:
1.ARC进行内存管理
2.适当情况下使用reuseIdentity 重用
3.尽可能将view设置为不透明(Opaque)
4.避免臃肿的xib
5.不要阻塞主线程
6.让图片的大小UIimageview一样
7.选择正确的合集-使用适合的类和对象编写代码
8.使用GZip压缩-使用GZip对网络传输中的数据进行压缩,减小文件的大小,并加快下载的速度,压缩对文本的数据特别有用,文本具有很高的压缩比,NSURLConnection默认已经支持GZip压缩
9.重用和延迟加载view
10.缓存
11.考虑绘制
12.处理内存警告
13.优化tableview
14.选择正确的数据储存方式
15.加速启动时间
16.使用Autorelease pool-临时对象不使用的时候,自动释放
17.缓存图片或不缓存-imageNamed加载图片的时候这个图片是有缓存下来,使用imageWithContentOfFile是没有缓存,如果经常使用到的则缓存下来比较合适
18.尽量避免Date格式化

转载于:https://www.cnblogs.com/diyigechengxu/p/9216461.html

本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 162202241@qq.com 举报,一经查实,本站将立刻删除。

最新评论

欢迎您发表评论:

请登录之后再进行评论

登录