【iOS】—— 离屏渲染

离屏渲染

UIView和CALayer关系

  • UIView继承于UIResponder,可以处理系统传递过来的事件,如:UIApplication、UIViewController、UIView,以及所有从UIView派生出来的UIKit类。每个UIView内部都有一个CALayer提供内容的绘制和显示。
  • CALayer继承于NSObject类,负责显示UIView提供的内容contents。CALayer有三个视觉元素:背景色,内容和边框,其中内容的本质是一个CGImage。

GPU屏幕渲染的两种方式

  • On- Screen Renderring(当前屏幕渲染)

    指的是GPU的渲染操作是在当前用于显示的屏幕缓冲区操作。

  • Off- Screen Renderring(离屏渲染)

​ 指的是在GPU在当前屏幕缓冲区之外开辟一个缓冲区进行渲染操作。

当前屏幕渲染,不需要额外创建新的缓存,也不需要开启上下文,相较于离屏渲染性能更好。当前屏幕渲染有些情况下的渲染解决不了,需要使用离屏渲染。

产生离屏渲染的原因

苹果系统不能够一次去处理视图,需要一张一张的处理视图,那么就需要开辟一个离屏缓存区去存储一张一张处理好的视图,开辟的这个离屏缓存区导致离屏渲染。

既然离屏渲染这么耗性能,为什么有这套机制呢?

有些效果被认为不能直接呈现到当前屏幕上,需要在其他地方做额外的处理,图层属性的混合体在没有愈合成之前不能直接加载到屏幕上,所以需要离屏渲染。

什么情况会离屏渲染?

  • 为图层设置遮罩(layer.mask)
  • 将图层的layer.masksToBounds / view.clipsToBounds属性设置为true
  • 将图层将图层layer.allowsGroupOpacity属性设置为YESlayer.opacity小于1.0
  • 为图层设置阴影(layer.shadow *)
  • 为图层设置光栅化layer.shouldRasterize=true
  • 具有layer.cornerRadiuslayer.edgeAntialiasingMasklayer.allowsEdgeAntialiasing的图层
    当然也不是所有的圆角都会导致离屏渲染。
  • 文本(任何种类,包括UILabelCATextLayerCore Text等)。
  • 使用CGContextdrawRect :方法中绘制大部分情况下会导致离屏渲染,甚至仅仅是一个空的实现。

既然离屏渲染这么不好,为什么我们还要强制开启呢?

当一个图像混合了多个图层,每次移动时,每一帧都要重新合成这些图层,十分消耗性能。当我们开启光栅化后,会在首次产生一个位图缓存,当再次使用时候就会复用这个缓存。但是如果图层发生改变的时候就会重新产生位图缓存。所以这个功能一般不能用于 UITableViewCell中,cell的复用反而降低了性能。最好用于图层较多的静态内容的图形。而且产生的位图缓存的大小是有限制的,一般是2.5个屏幕尺寸。在100ms之内不使用这个缓存,缓存也会被删除。所以我们要根据使用场景而定。

如何避免离屏渲染

1. 圆角的优化
  1. 使用贝塞尔曲线UIBezierPath和Core Graphics框架画出一个圆角。
  2. 使用CAShapeLayer和UIBezierPath设置圆角。

总的来说就是用CAShapeLayer的内存消耗少,渲染速度快,建议使用优化方案2。

2. shadow

对于shadow,如果图层是个简单的几何图形或者圆角图形,我们可以通过设置shadowPath来优化性能,能大幅提高性能。示例如下:

objective-c 复制代码
mageView.layer.shadowColor=[UIColorgrayColor].CGColor;
imageView.layer.shadowOpacity=1.0;
imageView.layer.shadowRadius=2.0;
UIBezierPath *path=[UIBezierPathbezierPathWithRect:imageView.frame];
imageView.layer.shadowPath=path.CGPath;

shouldRasterize属性值为YES来强制开启离屏渲染。其实就是光栅化(Rasterization)。

相关推荐
Smile_Gently4 小时前
Mac 系统 Node.js 安装与版本管理指南
macos·node.js
野盒子6 小时前
前端面试题 微信小程序兼容性问题与组件适配策略
前端·javascript·面试·微信小程序·小程序·cocoa
无知的前端7 小时前
Flutter开发,GetX框架路由相关详细示例
android·flutter·ios
大熊猫侯佩7 小时前
iOS 18 中全新 SwiftData 重装升级,其中一个功能保证你们“爱不释手”
数据库·ios·swift
大熊猫侯佩7 小时前
SwiftUI 6.0(iOS 18)新容器视图修改器漫谈
ios·swiftui·wwdc
Yale曼陀罗7 小时前
如何快速删除谷歌浏览器在mac启动台生成的网页图标
macos
尖椒土豆sss8 小时前
记一次macOs系统安装使用vpn过程
macos
Digitally9 小时前
如何将 iPhone 中的短信导出为 PDF
ios·pdf·iphone
帅次1 天前
Flutter Container 组件详解
android·flutter·ios·小程序·kotlin·iphone·xcode