【iOS高级资深工程师面试篇】①、2022年,金九银十我为你准备了《iOS高级资深工程师面试知识总结》 UI部分3/3 -UIView绘制原理-离屏渲染

iOS高级资深工程师面试篇系列 - 已更新3篇
UI部分1/3 -UITableView-事件传递&视图响应
UI部分2/3 -图像显示原理-UI卡顿&掉帧
UI部分3/3 -UIView绘制原理-离屏渲染

技术:iOS底层原理、事件传递、视图响应、图像显示原理、UI卡顿&掉帧、UIView绘制原理、离屏渲染

《iOS高级资深工程师面试知识总结》 UI部分3/3 -UIView绘制原理-离屏渲染

        • 一、UIView绘制原理
          • ❓面试考点: 往往出现`高级、资深工程师的考点之中` 请你说说UIView绘制的原理
          • 1. UIView绘制原理的流程图
          • 2. UIView系统绘制原理
          • 3. 异步绘制
          • ❓面试考点: 是否知道异步绘制、怎么进行异步绘制、异步绘制是怎么实现的
          • 异步绘制时序图
        • 二、离屏渲染
          • ❓面试考点: 1. 什么是离屏渲染? 、2. 你对离屏渲染是怎么样理解的呢? `微博、美团真机面试问题` 3. 我们在什么场景下会触发离屏渲染触发? 4.为何要避免离屏渲染
            • 1. 在屏渲染`当前屏幕渲染` - `On-Screen Rendering`
            • 2. 离屏渲染 - `Off-Screen Rendering`
            • 3. 离屏渲染何时会触发? - `初级、中级工程师会问到`
            • 4. 为何要避免离屏渲染?
      • UI视图面试总结
        • 1. 系统的UI事件传递机制是怎样的?
        • 2. 使UITableview滚动更流畅的方案或思路有哪些? - `高级、资深问题`
        • 3. 什么是离屏渲染?
        • 4. UIView和CALayer之间的关系是怎样的?

一、UIView绘制原理
❓面试考点: 往往出现高级、资深工程师的考点之中 请你说说UIView绘制的原理
1. UIView绘制原理的流程图
Created with Raphaël 2.3.0 [UIView setNeedsDisplay] [CALayer setNeedsDisplay] [CALayer display] layer.delegate respoendTo@selector(displayLayer:) 异步绘制入口 结束 系统绘制流程 yes no
  1. 当我们调用UIView的 setNeedsDisplay方法时候。
    系统会立即调用 [view.layer setNeedsDisplay]方法。相当于在layer上面打上了一个脏标记。
    然后再RunLoop即将结束的时候。才会调用[CALayer display]方法
    然后才进入我们视图真正绘制工作流程当中。
  2. 所以我们可以回答说,为什么UIView的调用 setNeedsDisplay方法并没有立刻发生对应视图的绘制工作。
    实际上是。当RunLoop将要结束的时候。才会开始进入视图绘制流程当中。
  3. CALayer的delegate是否会响应displayLayer。如果不响应 就进入 系统绘制流程
    如果CALayer的delegate 响应了 displayLayer方法的时候。 就会进入异步绘制入口
2. UIView系统绘制原理
YES
NO
CALayer creates backing store CGContextRef
layer has delegate?
layer.delegate drawLayer:inConext
UIView drawRect:
CALayer uploads backing store to GPU
CAlayer darwInContext:
结束

对于系统内部绘制流程

  1. 内部会创建一个 CALayer creates backing store(CGContextRef)
    我们可以理解为CGContextRef,CGContextRef方法当中可以通过上下文获取取出栈顶的context,拿到的就是当前控件的上下文或者是backing store
  2. 然后layer会进行判断。它是否有代理
    如果没有就会调用 [CALayer drawInContext]
    如果就会调用 [layer.delegate drawLayer:inContext:]
  3. 然后做当前视图的绘制工作 - 发生在系统内部绘制当中的
  4. 然后再合适的时机给予我们的一个回调方法[UIView drawRect:]
  5. drawRect默认实现 其实就是什么都不做的
    系统给我们开drawRect的铐子。其实就是允许我们在系统绘制的基础之上。做一些其他的绘制工作。
    不管哪两个分支。最终都是由CALayer的backing store 上传到 GPU
    最终就结束系统默认的流程
3. 异步绘制
❓面试考点: 是否知道异步绘制、怎么进行异步绘制、异步绘制是怎么实现的

【iOS高级资深工程师面试篇】①、2022年,金九银十我为你准备了《iOS高级资深工程师面试知识总结》 UI部分3/3 -UIView绘制原理-离屏渲染_第1张图片

如果layer.delegate 遵循了 displayLayer 方法
或者实现了 displayLayer 这个方法。我们就可以进入异步绘制流程当中
在这个异步绘制流程当中。需要代理去负责生成对应的bitmap,也就是我们所对应的位图
同时需要 设置bitmap 作为layer.contents属性的值

异步绘制时序图
main queue global queue [AsyncDrawingView setNeedsDisplay] [CALayer display] [AsyncDrawingView displayLayer:] CGBitmapContextCreate() [other work] CoreGraphic API CGBitmapContextCreateImage() [CALayer setContents:] main queue global queue

我们通过上方一个时序图来了解异步绘制机制和流程

  1. 左侧是一个主队列,右侧是一个全局并发队列
  2. 假如说 在某个时刻调用了 setNeedsDisplay方法之后呢
  3. 那么,在当前RunLoop将要结束之后,就会由系统调用 视图所对应Layer的[CALayer display]方法,然后如果我们的代理实现了 displayLayer 这个函数的时候,就会调用我们代理的displayLayer的这个函数方法
  4. 然后通过子线程的切换。在子线程当中,去做一个位图的绘制
    全局并发队列做的操作
    CGBitmapContextCreate()
    作用: 通过 CGBitmapContextCreate()这个函数创建一个位图的上下文
    CoreGraphic API
    作用: 通过 CoreGraphic相关的API,可以做一些当前UI控件视图的绘制工作
    CGBitmapContextCreateImage()
    作用: 通过CGBitmapContextCreateImage()函数 ,根据当前所绘制的上下文生成一张CGImage的图片。然后再回到主队列当中
  5. 主线程可以做其他的工作
  6. 等到子线程返回一张CGImage的图片到主队列当中。提交位图,设置给 [CALayer setContents:]属性。
    这样就完成了一个UI控件的异步绘制过程

二、离屏渲染
❓面试考点: 1. 什么是离屏渲染? 、2. 你对离屏渲染是怎么样理解的呢? 微博、美团真机面试问题 3. 我们在什么场景下会触发离屏渲染触发? 4.为何要避免离屏渲染

有离屏渲染就有在屏渲染

1. 在屏渲染当前屏幕渲染 - On-Screen Rendering

意为当前屏幕渲染,指的是GPU的渲染操作实在当前用于显示的屏幕缓冲区中进行
在屏渲染指的是GPU层面的一个概念

2. 离屏渲染 - Off-Screen Rendering

意为离屏渲染,指的是GPU在当前屏幕缓冲区以外新开辟一个缓冲区进行渲染操作

离屏渲染本身这个概念,起于GPU层面上面。
通俗语言来说明 离屏渲染:

  1. 也就是当我们设置视图的图层属性。如果在指定未愈合之前,不能用于直接显示的时候。就触发了离屏渲染。
  2. 典型的离屏渲染,设置视图的圆角属性,包括一些蒙层的遮罩。
  3. 当我们指定UI视图的某些属性,标记它为未愈合成之前,不能用于当前屏幕上直接显示的时候。就会触发了离屏渲染
  4. 离屏渲染的概念,起源于GPU层面上面:
    指的是GPU在当前屏幕缓冲区以外新开辟一个缓冲区进行渲染操作
3. 离屏渲染何时会触发? - 初级、中级工程师会问到
  1. 圆角(当和maskToBounds一起使用时)
    只有同时设置圆角和maskToBounds为YES的时候,才会触发离屏渲染
  2. 图层蒙版
  3. 阴影
  4. 光栅化
4. 为何要避免离屏渲染?
  1. CPU和GPU在进行具体视图绘制渲染的时候。做了大量的工作
  2. 离屏渲染发生在GPU层面上面的。
  3. 由于离屏渲染使GPU层面上面,触发了OpenGL的多通道渲染管线。产生了额外的开销。所以我们需要避免离屏渲染
    面试可以这样回答:
    高级、资深工程师的回答
    在触发离屏渲染会增加GPU的工作量。
    增加GPU的工作量。很有可能导致CPU和GPU工作耗时。加起来的总耗时大于16.7ms
    可能就回到导致UI的卡顿和掉帧
    所以我们需要避免离屏渲染
    初、中级工程师的回答
  4. 创建新的渲染缓冲区 - 存在着内存上的开销
  5. 上下文切换 - 因为有多通道渲染管线。需要把多通道的渲染结果做一个最终的合成。涉及到上下文切换。就有一个GPU的额外的开销

UI视图面试总结

1. 系统的UI事件传递机制是怎样的?

考察的是hitTest 和pointInside的实现

2. 使UITableview滚动更流畅的方案或思路有哪些? - 高级、资深问题

涉及到 性能优化的掌握程度。
可以从CPU或者GPU的考虑层面上进行说明。
对于CPU可以采用在子线程进行对象的创建、销毁。包括预排版、以及图片的解码。和采用异步绘制方案。
都是源于关于基于UI卡顿和掉帧的分析层面上

3. 什么是离屏渲染?

离屏渲染概念起源于GPU
在GPU层面上。如果在当前屏幕缓冲区以外新开辟一个缓冲区进行渲染操作
就是离屏渲染

为什么要避免离屏渲染?

4. UIView和CALayer之间的关系是怎样的?

UIView是专门做UI传递和事件响应的
CALayer完全是负责View的视图显示工作
这里包含一个六大原则中的一个
单一原则 - 涉及到一个面试题
为什么要区分UIView和CALayer的工作

你可能感兴趣的:(#,iOS-笔试题&面试题,iOS高级资深工程师,ios高级资深工程师面试总结,UIView绘制原理,离屏渲染,异步绘制)