UIView相关总结

一、UITableView相关

重用机制:cell=[tableView dequeueReusableCellWithIndentifier:identifier] 重用池 存 取 标识符 (图1)

存 滑出屏幕之外的cell 会被加入重用池

取 屏幕显示到第n个,继续滑动n+1就会从重用池中根据标识符取一个可重用的cell

标识符 若滑出屏幕的第1个和即将显示的第n+1个的标识符相同,第n+1个就会复用第1个控件创建的cell

自定义UI控件字母索引条:实现重用机制的类ViewReusePool,三个方法取,存,重置即使用中的视图移动到可重用队列中。等待使用的队列,使用中的队列

取:等待使用的队列,若没有就返回nil,若有把它从等待使用队列移除,加入到使用中队列,同时该视图返回给调用方

存:首先做异常判断,若视图为nil就什么都不做。添加视图到使用中的队列

重置:声明view是nil,然后遍历如果使用中的队列有使用中的视图,将其从使用中队列移除,加入等待使用的队列。

IndexedTableView 定义IndexedTableViewDataSource协议里定义一个获取索引条数据的方法,IndexedTableView里定义一个weak属性的数据源

定义一个装载视图的容器view和重用池;懒加载containerView并将其插入到当前视图最上面,避免索引条随着table滚动。懒加载重用池,标记所有视图为可重用状态,之后reload字母索引条。

数据源同步问题:数据源删除会引用LoadMore后降刷新,删除操作是用户交互操作,往往在主线程进行,而LoadMore在子线程进行。故涉及多线程对共享数据的访问。(图2)

解决方案:并发访问、数据拷贝(记录同时操作 大量数据拷贝时内存开销大)。数据拷贝一般在主线程,拷贝后的结果给子线程使用,同时在子线程进行新数据的网络请求、解析、预排版。主线程删一行数据,reloadUI后数据消失不见了,主线程有事件会做其他工作,子线程会返回请求的结果,reloadUI会包含数据删除前的数据。主线程记录删除操作,子线程将要返回数据更新UI的时候,同步一下该删除操作,然后回到主线程同步UI。(图3)
 

缺点:需要记录数据同步删除动作;存在大量数据源的拷贝,内存开销较大

串行访问:GCD中串行队列 ;子线程中进行网络请求、数据解析,将请求回来的网络数据放到 串行队列进行新增数据预排版;此时主线程删除某数据需要以同步的方式在串行队列中处理,主线程就需要等前一个block任务完成后再同步主线程数据删除操作,最后回到主线程更新UI。(图4)

缺点:若子线程处理任务特别耗时,某删除动作可能会有延时。

二、事件传递和响应机制

2.1事件传递机制:从上至下即UIApplication->UIWindow->hitTest:withEvent:返回最终响应的视图->

若不可交互则父遍历兄弟节点视图,若可交互则调用pointInside:withEvent:判断当前点击的点是否在window范围内,是则倒序遍历子视图,在每子视图都调用hitTest:withEvent:即递归调用,

有则该视图为最终响应者,无且在Window范围内则window作为最终响应者。

2.2事件响应机制:从下至上即UI控件->UIView->若有则UIViewController->UIWindow->UIApplication->UIApplicationDelegate

若最终无视图处理该事件,则忽略,当作什么都没有发生。

三、图像显示原理:

3.1CPU 在合适时机回调drawRect方法绘制好位图,经过总线 在合适时机 由CoreAnimation 传给GPU 的OpenGL(ES)渲染管线

CPU工作:LayoutUI布局/文本计算、DIsplay绘制如drawRect、Prepare图片编/解码、Commit提交位图

3.2GPU 对拿到的位图进行图层渲染和纹理合成,处理结果放到 帧缓冲区的FrameBuffer中

GPU渲染管线:顶点着色、图源装配 光栅化 片段着色/处理

3.3视频控制器 根据Vsync信号在指定时间之前提取对应缓冲区对应的屏幕显示内容,讲内容显示到屏幕

四、UI卡顿、掉帧原因

4.1卡顿、掉帧产生原因:

界面滑动流畅性60F/S帧/秒,即16.7ms产生一帧画面,CPU在一定时间内绘制好并输出位图给GPU,CPU进行图层合成管理渲染,两者协同产生一帧数据,在Vsync垂直信号来到之前就得准备好需要显示的画面。若CPU工作时长过长,留给GPU渲染合成图片的时间就非常少,这样完成总时间若超过16.7ms,下一帧Vsync到来前还没准备好该画面,就会视觉上出现滑动卡顿。

4.2滑动优化方案:

CPU 对象的创建/调整/销毁、预排版(布局、文本计算)、预渲染(文本异步绘制、图片编解码)放到子线程,这样主线程就有更多的时间响应交互。

GPU减少纹理渲染,依托CPU异步绘制减轻GPU压力、减少视图复杂度(视图层级复杂,GPU需做大量的计算进行视图合成、像素点对应像素值合成)

五、UIView绘制原理、异步绘制

5.1 UIView绘制原理:

调用 [ UIView setNeedsDisplay]并不立刻绘制,而在之后某一时机才进行当前视图的真正绘制。

而是调用view.layer的同名方法[view.layer setNeedsDisplay],相当于给layer打上了标记,再当前runloop将要结束时才会调用[CALayer display],这个时候才真正开始绘制工作。

在[CALayer display]内部会判断layer.delegate respondsToSelector:@selector(displayLayer:),若不响应,开始系统绘制流程;若响应,提供异步绘制入口。

5.2系统绘制流程:

CALayer内部创建backingstore(CGContextRef) 一般在drawRect方法中可以通过上下文堆栈取出栈顶的Context,拿到当前视图或控件的上下文,然后该layer会判断是否有delegate,若无则调用[CALyer drawInContext:],若有调用[layer.delegate drawLayer:inContext:]做当前视图的绘制工作,这步发生在系统内部,在合适时机给予一个回调方法[UIView drawRect:],开这个口子允许做一些其他绘制工作;这两个分支最终都是CALayer上传backing store到GPU,结束。

5.3异步绘制:

[layer.delegate drawLayer:]代理负责生成对应的bitmap,设置该bitmap作为layer.contents属性的值。

主队列 在某一时机调用[AsyncDrawingView setNeedsDisplay]方法,在当前runloop将要结束时,由系统调用[CALayer display],若代理实现了display函数,

然后通过子线程全局并发队列切换做位图绘制CGBitmapContextCreate( )创建位图上下文、CoreGraphicAPI当前UI绘制工作、CGBitmapContextCreateImage( )根据当前绘制的上下文生成CGImage图,然后回到主队列中设置[CALayer setContents]

六、离屏渲染

在当前屏幕缓冲区以外新开辟一个缓冲区进行渲染操作,未合成前不能直接显示。

layer的圆角与maskToBounds一起用、阴影、蒙层、光栅化都会触发离屏渲染。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值