美文网首页
1.1、iOS面试题之ui

1.1、iOS面试题之ui

作者: zmfflying | 来源:发表于2020-06-14 14:40 被阅读0次

    1.UITableview的优化方法(缓存高度,异步绘制,减少层级,hide,避免离屏渲染)

    可能造成tableView卡顿的原因有:

    1.最常用的就是cell的重用, 注册重用标识符 如果不重用cell时,每当一个cell显示到屏幕上时,就会重新创建一个新的cell;如果有很多数据的时候,就会堆积很多cell。如果重用cell,为cell创建一个ID,每当需要显示cell 的时候,都会先去缓冲池中寻找可循环利用的cell,如果没有再重新创建cell

    2.避免cell的重新布局 cell的布局填充等操作 比较耗时,一般创建时就布局好,如可以将cell单独放到一个自定义类,初始化时就布局好

    3.提前计算并缓存cell的属性及内容 当我们创建cell的数据源方法时,编译器并不是先创建cell 再定cell的高度。而是先根据内容一次确定每一个cell的高度,高度确定后,再创建要显示的cell,滚动时,每当cell进入凭虚都会计算高度,提前估算高度告诉编译器,编译器知道高度后,紧接着就会创建cell,这时再调用高度的具体计算方法,这样可以方式浪费时间去计算显示以外的cell

    4.减少cell中控件的数量 尽量使cell得布局大致相同,不同风格的cell可以使用不用的重用标识符,初始化时添加控件, 不适用的可以先隐藏

    5.不要使用ClearColor,无背景色,透明度也不要设置为0 渲染耗时比较长

    6.使用局部更新 如果只是更新某组的话,使用reloadSection进行局部更新

    7.加载网络数据,下载图片,使用异步加载,并缓存

    8.少使用addView 给cell动态添加view

    9.按需加载cell,cell滚动很快时,只加载范围内的cell

    10.不要实现无用的代理方法,tableView只遵守两个协议

    11.缓存行高:estimatedHeightForRow不能和HeightForRow里面的layoutIfNeed同时存在,这两者同时存在才会出现“窜动”的bug。所以我的建议是:只要是固定行高就写预估行高来减少行高调用次数提升性能。如果是动态行高就不要写预估方法了,用一个行高的缓存字典来减少代码的调用次数即可

    12.不要做多余的绘制工作。在实现drawRect:的时候,它的rect参数就是需要绘制的区域,这个区域之外的不需要进行绘制。例如上例中,就可以用CGRectIntersectsRect、CGRectIntersection或CGRectContainsRect判断是否需要绘制image和text,然后再调用绘制方法。

    13.预渲染图像。当新的图像出现时,仍然会有短暂的停顿现象。解决的办法就是在bitmap context里先将其画一遍,导出成UIImage对象,然后再绘制到屏幕;

    14.使用正确的数据结构来存储数据。

    2.如何检测应用是否卡顿

    https://blog.csdn.net/u010262501/article/details/79616963

    https://blog.csdn.net/mK0vouYv4BwgX190fSd/article/details/103415656

    1、YYFPSLabel:监测FPS,实现原理实现原理是向主线程的RunLoop的添加一个commonModes的CADisplayLink,每次屏幕刷新的时候都要执行CADisplayLink的方法,所以可以统计1s内屏幕刷新的次数,也就是FPS了

    2、GCDFetchFeed:大部分导致卡顿的的方法是在kCFRunLoopBeforeSources和kCFRunLoopAfterWaiting之间,比如source0主要是处理App内部事件,App自己负责管理(出发),如UIEvent(Touch事件等,GS发起到RunLoop运行再到事件回调到UI)、CFSocketRef。开辟一个子线程,然后实时计算 kCFRunLoopBeforeSources 和 kCFRunLoopAfterWaiting 两个状态区域之间的耗时是否超过某个阀值,来断定主线程的卡顿情况,连续3次超时80ms认为卡顿。

    3、ANREye:子线程Ping,创建一个子线程通过信号量去ping主线程,因为ping的时候主线程肯定是在kCFRunLoopBeforeSources和kCFRunLoopAfterWaiting之间。每次检测时设置标记位为YES,然后派发任务到主线程中将标记位设置为NO。接着子线程沉睡超时阙值时长,判断标志位是否成功设置成NO,如果没有说明主线程发生了卡顿。

    4、通过Instrument设置16ms的采样率

    5、KMCGeigerCounter:KMCGeigerCounter是一个iOS帧速计算器,像盖革计数器那样,当动画丢失一帧时它就记录一次。 KMCGeigerCounter可以让你观测到掉落5帧的情况,可以通过这个来检测app的卡顿程度。KMCGeigerCounter弄了一个FPS监控条,通过CADisplayLink来获取屏幕刷新频率,在使用过程中就能即时知道什么页面流畅什么页面会卡顿。 

    3.UICollectionView自定义layout如何实现?

    https://blog.csdn.net/qq_34900204/article/details/74626050

    自定义一个类继承自UICollectionViewLayout类,重写父类方法

    4.点击屏幕,到响应事件,经历了什么?

    https://www.jianshu.com/p/6ff87b3ab2cb

    响应链,顾名思义,就是有一系列响应对象的集合成的一个层次结构。那什么又是响应对象呢?Cocoa里面规定:凡是继承于UIResponder或者UIResponder的子类的对象都可以作为响应对象,比如UIApplication、UIViewController和UIView。

            在响应用户触摸等事件中,APP具体会通过下面三步来完成操作:

            1.  生成事件。当用户点击屏幕时,会产生一个触摸事件,并放入由Application管理的事件队列中,然后在队列中取出最前面的事件交给Window处理。

            2.  查找第一响应对象。Window收到事件后会在视图层次结构中找到最适合的一个视图来处理事件,通常一个窗口中最适合处理当前事件的对象称为第一响应对象。

            3.  处理事件。通常最后是第一响应对象处理事件,如果第一响应对象无法处理事件,就会把事件传递给下一个响应对象,直到Application。如果Application也无法处理,那就丢弃掉此事件。

            在上述系列操作中,所参与到的UIApplication、UIViewController和UIView就作为响应对象构成这次事件的响应链。

    5.view的视图树结构是怎么样的?

    https://www.cnblogs.com/ihojin/p/view-recursivedescription.html

    在想要查看的 UIView 附近打个断点,运行,直到停在断点处,在控制台键入:po [view recursiveDescription],回车。

    6.同时画阴影和圆角,怎么实现?

    https://www.cnblogs.com/widgetbox/p/9378482.html

    不设置 masksToBounds

    7.GPU渲染原理,离屏渲染问题如何解决?

    https://www.jianshu.com/p/cff0d1b3c915

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

    iOS 9.0 之后UIButton设置圆角会触发离屏渲染,而UIImageView里png图片设置圆角不会触发离屏渲染了,如果设置其他阴影效果之类的还是会触发离屏渲染的。

    使用CAShapeLayer和UIBezierPath设置圆角

    当我们需要圆角效果时,可以使用一张中间透明图片蒙上去

    使用ShadowPath指定layer阴影效果路径

    使用异步进行layer渲染(Facebook开源的异步绘制框架AsyncDisplayKit)

    设置layer的opaque值为YES,减少复杂图层合成

    尽量使用不包含透明(alpha)通道的图片资源

    尽量设置layer的大小值为整形值

    直接让美工把图片切成圆角进行显示,这是效率最高的一种方案

    很多情况下用户上传图片进行显示,可以让服务端处理圆角

    使用代码手动生成圆角Image设置到要显示的View上,利用UIBezierPath(CoreGraphics框架)画出来圆角图片

    对于离屏渲染的检测,苹果为我们提供了一个测试工具Core Animation。可以在Xcode->Open Develeper Tools->Instruments中找到

    8.核心动画

    核心动画只能添加到CALayer, 核心动画一切都是假象,并不会改变真实的值。如果需要与用户交互就使用UIView的动画. 不需要与用户交互可以使用核心动画。

    在转场动画中,核心动画的类型比较多。根据⼀个路径做动画,只能用核心动画(帧动画) 、动画组:同时做多个动画。

    CAAnimation是所有动画对象的父类,负责控制动画的持续时间和速度,是个抽象类,不能直接使用,应该使用它具体的子类

    CABasicAnimation——基本动画 是CAPropertyAnimation的子类,fromValue:keyPath相应属性的初始值  toValue:keyPath相应属性的结束值

    CAKeyframeAnimation——关键帧动画也是CAPropertyAnimation的子类,与CABasicAnimation的区别是:

    CABasicAnimation只能从一个数值(fromValue)变到另一个数值(toValue),而CAKeyframeAnimation会使用一个NSArray保存这些数值。

    CAAnimationGroup——动画组,是CAAnimation的子类,可以保存一组动画对象,将CAAnimationGroup对象加入层后,组中所有动画对象可以同时并发运行

    CATransition——转场动画 能够为层提供移出屏幕和移入屏幕的动画效果。UINavigationController就是通过CATransition`实现了将控制器的视图推入屏幕的动画效果。如果父视图中的两个子视图互相切换,转场动画应加给父视图!

    相关文章

      网友评论

          本文标题:1.1、iOS面试题之ui

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