# UI视图相关

2018-06-04  本文已影响0人  Sendom

UI视图相关

  1. UITableView
  2. 事件传递&视图响应
  3. 图像显示原理
  4. 卡顿&掉帧
  5. 绘制原理&异步绘制
  6. 离屏渲染

1. UITableView

  1. 重用机制
  2. 数据源同步(多线程)

重用机制

  1. cell = [UITableView dequeueReusableCellWithIdentifier:@"identifier"];
  2. 不在屏幕上的cell 放到重用池中,即将在屏幕上显示的cell用相同的重用标识符从重用池中取得缓存的cell

数据源同步(UI刷新错乱)

  1. 并发访问,数据拷贝
  2. 串行访问

2. 事件传递&视图响应

  1. UIView和CALayer
  2. 事件传递与视图响应链

1. UIView和CALayer

  1. UIView显示的部分是CALayer的contents(backing store),UIView的backgroundColor是CALayer的同名属性的封装
  2. 区别
    1. UIView 为CALayer提供显示的内容,以及负责触摸灯事件,参与响应链(设计原则,单一职责原则)
    2. CALayer只负责内容contents的显示

2. 事件传递与视图响应链

  1. 涉及的两个方法hitTest:withEvent:(方法一)与pointInside:withEvent:(方法二)

  2. 流程:

    1. 用户点击了屏幕,硬件接收到点击事件后,由UIKit(硬件驱动)处理包装事件,发送给桌面,如果桌面当前没有程序在运行,就转换成自己的事件,如点击APP图标启动APP,滑动APP列表,或者打开通知中心等。如果有APP在前台运行,就把事件传给APP,APP会利用RunLoop处理事件。
    2. App会把事件分发给当前的UIWindow对象,UIWindow对象会调用方法一返回对应的视图。在调用方法一之前会判断当前视图不是是隐藏,用户交互是enable,透明度大于0.01,然后调用方法二,检测触摸点是否在本视图之内,如果不在则不进行方法一,如果在就会用倒叙的方法遍历自己的子视图,让他们走一遍方法二与方法一,如果子视图方法一返回的UIView不为空则让这个UIView处理点击事件,如果他不处理就让他的父视图处理,以此类推,最后都没有视图响应就丢弃。
  3. 事件响应

    1. touchesBegan(Modved)(Ended):withEvent:

3. 图像显示原理

设计工作单位

  1. cpu
  2. gpu:涂层渲染,纹理合成
  3. 帧缓冲区:gpu产生的数据
  4. 视频控制器:把帧缓冲去的数据显示到显示器
  5. 显示器

UI具体显示

  1. CALayer(内容布局等计算)(cpu负责)
  2. Core Animation(cpu负责)
  3. OpenGL(ES)(GPU负责)
  4. Screen

cpu具体流程

  1. 布局计算(UI布局,文本计算)
  2. 显示计算(drawRect:)
  3. 其他一些准备工作(图片编解码)
  4. 提交内容给GPU(提交位图)

GPU渲染管线(OpenGL渲染管线)

  1. 顶点着色
  2. 图元装配
  3. 光栅化
  4. 片段着色
  5. 片段处理
  6. 把最终的像素点提交到帧缓冲区中(视频控制器会在VSync(垂直同步)到来时显示在屏幕上)

4. 卡顿&掉帧

  1. 原因
  2. 解决方案

1. 原因

  1. 16.7ms产生一帧画面
  2. cpu+gpu提交一次帧缓冲区的时间和小于16.7ms
  3. 时间大于这个时间 就会产生掉帧,卡顿现象

2. 解决方案

  1. 从cpu
    1. 对象的创建调整销毁(子线程)
    2. 预排版 (布局计算,文本计算)
    3. 预渲染(文本异步绘制,图片编码等)
  2. 从GPU
    1. 纹理渲染(离屏渲染)
    2. 视图混合(视图复杂,减轻视图复杂程度)

5. 绘制原理&异步绘制

  1. UIView对象调用setNeedsDisplay方法,就会调用他的layer的同名方法
  2. layer标记自己需要在runloop休眠时刷新自身contents-[layer display]
  3. 在刷新自身content算的时候会判断自身的delegate是否响应了displayLayer:方法,如果没有就走系统绘制流程,如果有则走用户自定义的绘制流程(这也是异步绘制的突破点)

系统绘制流程

  1. CALayer 创建 backing store(CGContextRef)
  2. layer代理没有响应方法
  3. CALayer 调用drawInContext:
  4. CALayer 上传backing store
  5. 结束

自定义绘制流程

这个过程要求代理自己生成响应的bitmap(位图),并且把bitmap设置为layer.contents的值。

  1. 会在相应代理方法后调用代理绘制方法
    1. CGBitmapContextCreate()
    2. CoreGraphic API
    3. CGBitmapContextCreateImage()
  2. 回调UIView 的 drawRect:让用户做一些其他自定义的事情
  3. 上传backing store

6. 离屏渲染-Off-Screen rendering

  1. 相对应的On-Screen Rendering
  2. Off-Screen rendering

1. 相对应的On-Screen Rendering

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

2. Off-Screen rendering

GPU在当前屏幕缓冲区以外新开辟的一个缓冲区进行渲染操作

触发条件

  1. 圆角与maskToBounds 一起设置
  2. 图层蒙版
  3. 阴影
  4. 光栅化

为什么避免

增加GPU工作量,导致GPU工作时间增长

  1. 新的渲染缓冲区
  2. 上下文的切换
上一篇下一篇

猜你喜欢

热点阅读