1:tableView 有什么好的性能优化方案?
CPU(Central Processing Unit,中央处理器)对象的创建和销毁、对象属性的调整、布局计算、文本的计算和排版、图片的格式转换和解码、图像的绘制(Core Graphics) GPU(Graphics Processing Unit,图形处理器)纹理的渲染 在iOS中是双缓冲机制,有前帧缓存、后帧缓存 卡顿产生的原因:因为CPU或者GPU所花费的时间过长,导致垂直信号来的时候,CPU计算或者GPU渲染未完成,从而掉帧。
卡顿解决的主要思路
(1) 尽可能减少CPU、GPU资源消耗 (2) 按照60FPS的刷帧率,每隔16ms就会有一次VSync信号
1.3 减轻CPU负荷
1.3.1 提前计算好cell的高度,缓存在相应的数据源模型中 1.3.2 尽可能的减少storyboard,xib的使用 1.3.3 滑动过程中尽量减少重新布局
1.4 按需加载
// 按需加载 - 如果目标行与当前行相差超过指定行数,只在目标滚动范围的前后指定3行加载。
- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset
1.5 异步绘制
当视图层级比较多的时候,可以采用异步绘制的方式,通过UIGraphics将内容绘制然后生成一张图片进行展示。 1.5.1 处理数据源 1.5.2 异步绘制数据
1.6 延时加载图片
监听runloop的状态,每次即将休眠的时候,即处于kCFRunLoopBeforeWaiting状态时才去绘制加载图片
2: 界面卡顿和检测你都是怎么处理?
页面卡顿是由哪些原因导致的? 1.死锁: 主线程拿到锁A, 需要获取锁B, 而同时子线程拿了锁B, 需要锁A, 这时主线程等待锁B的释放, 子线程等待锁A的释放, 相互等待. 2.抢锁: 主线程需要访问DB, 而这时某个子线程往DB插入数据. 通常抢锁的体验就是卡顿一阵子就恢复了. 3.主线程大量IO: 主线程为了方便直接写入大量数据, 导致页面卡顿. 4.主线程大量计算: 程序中的算法不合理, 大量循环等操作, 导致主线程某个函数占用大量CPU. 5.大量的UI绘制: 复杂的UI, 图文混排等, 带来大量的UI绘制.
卡顿问题怎么定位?
1.死锁一般会伴随Crash, 我们可以通过Crash日志进行分析.
2.抢锁的问题不太好办, 我们能将锁等待的时间打印出来, 但我们还需要知道是谁占用了锁, 可以检测Runloop的执行,观察耗时.
3.大量的IO可以在函数开始结束打点, 将函数占用时间打到日志中.
4.线程大量计算同理也可以将耗时记录到日志中.
5.大量UI绘制一般是难免的, APP中总会有复杂页面的绘制, 我们可以用AsnycDisplayKit等框架进行预排版,异步绘制,图片解码等.
如果我们能将上述问题发生时线程的堆栈信息捕捉下来, 那么就能快速定位到问题, 从而问题迎刃而解. 所以, iOS卡顿检查的思路就是创建一个子线程, 监控主线程Runloop的执行, 观察执行耗时是否超过预阈值, 如果有就立即记录线程堆栈.
如何判断主线程是否发生了卡顿?
FPS降低 CPU占用率很高 主线程Runloop执行了很久
FPS能够兼容后面两个特征, 但在实际操作过程中发现FPS不好衡量抖动比较大. 对于抢锁或者大量IO的情况, 光靠CPU是不行的, 所以一般检测判断, CPU占用是否超过了100%, 主线程Runloop执行是够超过阈值.
3:谈谈你对离屏渲染的理解?
什么是离屏渲染
Off-Screen Rendering意为离屏渲染,指的是GPU在当前屏幕缓冲区以外新开辟一个缓冲区进行渲染操作
为什么需要离屏渲染
因为在帧缓冲区渲染一个视图到屏幕中就抛弃的机制.所以当我们有多组视图需要组合随后统一处理的时候.需要在屏缓冲区额外开辟一个离屏的缓冲区去记录这些视图.随后统一处理.最后渲染显示出来
什么情况下会产生离屏渲染呢?
1.按钮添加图片以后做圆角处理 2.图片视图添加背景色和图片以后做圆角处理 2.mask遮罩 3.光栅化 4.组合视图设置透明度 5.阴影 6.渐变 7.绘制文字 8.系统毛玻璃效果
######如何避免离屏渲染?
1.针对圆角的离屏渲染的情况.我们可以通过四种方案.
a.使用一个镂空圆角视图盖在上面
b.使用YYImage里面的圆角方法
C.通过CALayer与UIBezierPath结合使用的
2.如果视图不能被复用.并且不是静态.需要被频繁修改的情况不建议开启光栅化.因为这样会开启离屏渲染会影响效率
3.尽量少使用或不使用透明度
4.异步绘制.减少图层
4:如何降低APP包的大小
降低包大小需要从两方面着手
a.可执行文件
编译器优化 Strip Linked Product、Make Strings Read-Only、Symbols Hidden by Default 设置为 YES 去掉异常支持,Enable C++ Exceptions、Enable Objective-C Exceptions 设置为 NO, Other C Flags 添加 -fno-exceptions 利用 AppCode 检测未使用的代码:菜单栏 -> Code -> Inspect Code 编写LLVM插件检测出重复代码、未被调用的代码
.资源
资源包括 图片、音频、视频 等 优化的方式可以对资源进行无损的压缩 去除没有用到的资源
5:日常如何检查内存泄露?
a.Leaks动态检测 项目运行起来-Product-Profile-instruments-Leaks b.Analyze静态分析 Product-Profile-Analyze c.只能解决oc中使用C语言导致的内存泄漏 运用MLeaksFinder-精准 iOS 内存泄露检测工具
6:APP启动时间应从哪些方面优化?
app启动过程 iOS应用的启动可分为pre-main阶段和main()阶段,pre-main阶段为main函数执行之前所做的操作,main阶段为main函数到首页展示阶段。其中系统做的事情为:
premain
加载所有依赖的Mach-O文件(递归调用Mach-O加载的方法) 加载动态链接库加载器dyld(dynamic loader) 定位内部、外部指针引用,例如字符串、函数等 加载类扩展(Category)中的方法 C++静态对象加载、调用ObjC的 +load 函数 执行声明为attribute((constructor))的C函数
main
调用main() 调用UIApplicationMain() 调用applicationWillFinishLaunching 通常的premain阶段优化即为删减无用的类方法、减少+load操作、减少attribute((constructor))的C函数、减少启动加载的动态库。而main阶段的优化为将启动时非必要的操作延迟到首页显示之后加载、统计并优化耗时的方法、对于一些可以放在子线程的操作可以尽量不占用主线程。