美文网首页iOS高手
iOS面试之UI视图模块

iOS面试之UI视图模块

作者: 木子心语 | 来源:发表于2019-11-20 18:00 被阅读0次

    UI视图内容如下:

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


    UI视图.png

    1.UITableView

    • 1.1重用机制
    为什么要用重用机制?
    UITableView是可以滚动的一个控件,当UItableView回滚时,如果不用重用
    机制会重复初始化原来已初始化的cell,所以用重用机制会节省性能,避免
    出现一些网络因素而造成的卡顿现象.
    
    • 1.2 数据源同步问题
    主线程.png
    1.比如一组数据源
    2.我们突然想删除某条数据,删除操作必须在主线程中完成,这个时候问题就来了,如何同步数据源?
    
    数据源同步1.png 数据源同步2.png
    数据源同步解决方案
    1.并发访问,数据拷贝
    
    案例:主线程与子线程(如上图)
    - 数据拷贝在主线程当中,拷贝的结果会给子线程使用,进行网络请求
    - 在子线程进行网络请求,数据解析的过程中,我们在主线程中删除一行数据,刷新UI,这条删除的数据就不存在了
    - 如果还有时间,主线程做其他的工作
    - 子线程返回请求的接口,有刷新一下UI,此时问题就出现了????
    子线程使用的是主线程中的数据拷贝,再删除一行数据之前进行的操作.
    我们删除的数据有重新出现了.怎么解决数据源同步问题呢?
    
    (数据源同步2)我们可以在主线程中记录删除操作,我们在子线程即将刷新
    UI时,进行同步删除操作,在主线程刷新UI就能保证数据源同步
    
    
    数据源同步3.png
    数据源同步解决方案
    2.串行访问
    
    案例:主线程与子线程,串行队列(数据源同步3)
    - 子线程进行网络请求,数据解析等操作
    - 请求的网络数据,在串行队列中进行数据预排版
    - 在主线程删除某一行数据,此时子线程预排版结束后,删除操作需要等待
    - 在串行队列中,完成上一个任务,在主线程发来的任务中,同步数据删除
    - 回到主线程更新UI,保证数据源同步.
    

    2.事件传递/视图响应

    2.1 UIView 和 CALayer
    UIView提供内容,负责处理触摸等事件,参与响应链
    CALayer负责显示内容
    
    2.2 事件传递
    //点击了那个视图
    -(UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event;
    //点击位置是否在当前视图内
    -(BOOL)pointInside:(CGPoint)point wihtEvent:(UIEvent*)event;
    

    2.3 事件传递流程

    事件传递流程.png
    点击屏幕-->>UIApplication-->>UIWindow-->>最终响应的视图-->>
    判断点击的视图是否在UIWindow范围内-->>视图遍历(最后添加的视图
    优先遍历)-->>返回的view1如果存在就结束了
    
    视图遍历流程.png
    - 开始遍历
    - 视图没有隐藏/视图存在点击事件/透明度不为0,视图存在,继续进行,否则返回nil
    - 判断点击视图是否在当前视图内,视图存在,继续下一级进行,否则返回nil
    - 遍历视图,通过响应视图hitTest方法,判断视图是否存在,如果不存在,继
    续遍历,直到找到最后的响应视图.
    - 遍历子视图,如果视图不存在,结果为上一层视图v
    
    • 2.4 视图事件响应
    -(void)touchesBegan:(NSSet*)touches withEvent:(UIEvent *)event;
    -(void)touchesMoved:(NSSet*)touchues withEvent:(UIEvent*)event;
    -(void)touchesEnded:(NSSet*)touches withEvent:(UIEvent*)event;
    
    UIResponder的响应方法,UIView继承UIResponder,所以UIView也有这三个方法
    
    面试题:如果传递到UIApplicationDelegate,最终仍然没有任何视图去处理事件,最终是什么样的场景?
    忽略这个事件,当做没有发生.
    

    3.图像显示原理

    • 3.1


      图像显示原理1.png
    - CPU,GPU两个硬件都是通过总线连接起来的
    - 在CPU中输出的结果,是一个位图.
    - 通过总线,在合适的时机,在上传给GPU
    - GPU拿到这个位图后,会做一些图层的渲染,纹理的合成,最终会把结果帧缓冲器当中(Frame Buffer)
    - 随后视频控制器会按照vsync信号逐行读取帧缓冲区的数据,最后显示到我们的显示器上.
    
    图像显示原理2.png
    - 我们创建的UIView,是通过CALayer负责的
    - CALayer中有个contents属性,绘制屏幕上的位图
    - 比如Hello world ,通过drawRect绘制位图
    - 绘制的位图,通过Core Anmation框架,提交GPU(OpenGL渲染管线),位图
    的渲染及纹理的合成,就会显示在屏幕上面.
    
    CPU工作.png
    - CPU工作:布局,显示,准备,提交.
    - Layout:UI布局,文本计算
    - Display:绘制
    - Prepare:图片编解码
    - Commit:提交位图
    
    GPU渲染管线.png
    补充:
    - GPU渲染管线:顶点着色,图元装配,光栅化,片段着色,片段处理
    - 经过以上5点:提交到帧缓存区当中,通过视频控制器,显示到我们的显示器
    

    4.UI卡顿,掉帧的原因

    UI卡顿,掉帧1.png
    - 页面的滑动流畅性是60FPS
    - 每一秒,会有60帧画面更新,人眼看到的就是流畅的.
    
    UI卡顿,掉帧2.png
    在规定的16.7ms内,在下一帧VSync到来前,CPU和GPU并没有完成下一帧画面的合成,导致卡顿和掉帧.
    
    • 滑动优化方案
    - CPU:
    - 对象创建,调整,销毁可以放到子线程中,节省CPU的时间
    - 预排版(布局,文本计算),放到子线程中,主线程响应用户的交互
    - 预渲染(文本等异步绘制,图片编解码等)
    
    - GPU:
    - 纹理渲染
    - 视图混合:减轻视图层级的复杂性,减轻GPU的压力
    

    5.绘制原理

    绘制原理.png
    [UIView setNeedsDisPlay] 
    |
    [view.layer setNeedsDisplay]
    |
    [CALayer display]
    
    - 如果不响应displayLayer方法,就会进入到系统绘制流程当中
    - 如果响应displayLayer方法,就开启了异步绘制
    
    • 系统绘制


      系统绘制流程.png
    - 使用layer的代理方法
    - 如果使用,调用系统的drawlayer方法,进行视图绘制
    - 如果不使用,调用drawinContext方法
    - 最终是对CALayer上传位图到GPU
    
    • 异步绘制
    - [layer.delegate displayLayer:]
    - 代理负责生成对应的位图
    - 位图作为layer.contents属性的值
    
    异步绘制流程.png
    - 在主队列调用setNeedsDisplay
    - 在当前runloop将要结束的时候,调用display方法,代理实现displayLayer函数,调用displayLayer方法
    - 通过子线程切换,位图绘制
    - 子线程中三个方法,CGBitmapContextCreate(),创建位图上下文
    - 通过CoreGraphic API进行位图绘制工作
    - 通过位图上下文生成图片
    - 回到主队列当中,提交位图,设置CALayer的content属性
    - 即完成了CALayer的异步绘制.
    

    6.离屏渲染

    • 当前屏幕渲染
    GPU的渲染操作是在当前用于显示的屏幕缓冲区中进行
    
    • 离屏渲染
    GPU在当前屏幕缓冲区以外新开辟一个缓冲区进行渲染操作
    
    离屏渲染何时会触发?
    - 圆角(与maskToBounds一起使用时)
    - 图层蒙版
    - 阴影
    - 光栅化
    
    为什么要避免离屏渲染?
    - 创建新的渲染缓冲区
    - 上下文切换
    
    增加GPU进行额外的开销,导致CPU和GPU合成大于16.7ms,会造成UI卡顿,掉帧
    

    UI视图面试题:

    • 系统的UI事件传递机制是怎样的?
    • UITableView滚动更流畅的方案?
    • 什么是离屏渲染?
    • UIView和CALayer之间的关系是怎样的?

    QQ交流群: 796142709

    相关文章

      网友评论

        本文标题:iOS面试之UI视图模块

        本文链接:https://www.haomeiwen.com/subject/uatoictx.html