Light's Blog

The best or nothing.

iOS知识小集-201912

| Comments

2019.12.04

ASR service 增加 enable remote silence。

2019.12.06

present 同一个VC会crash。
UI操作要放到主线程。

2019.12.09

iOS 启动优化

启动过程

冷启动:不在内存,也不存在进程。
热启动:APP结束后再启动,有部分在内存但没有进程存在。
resume:APP没结束,全在内存内存中,进程也存在。

iOS启动过程:
• 根据 info.plist 里的设置加载闪屏,建立沙箱,对权限进行检查等;
• 加载 Mach-O;
• 执行 attribute 的 constructor 函数;
• 加载类扩展;
• 加载 C++静态对象;
• 调用+load 函数;
• 执行 main 函数;
• Application 初始化,到 applicationDidFinishLaunchingWithOptions 执行完;
• 初始化帧渲染,到 viewDidAppear 执行完,用户可见可操作。

分析工具

Instruments,App launch。

分析纬度

线程是计算机资源调度和分配的基本单位,CPU 的使用情况会体现到线程上。

主线程耗时:

​ 1、使用 Messier 生成 trace json 进行分析。
​ 2、手动 hook objc_msgSend 生成 Objective-C 方法耗时数据分析。GCDFetchFeed/SMCallTraceCore.c at master · ming1016/GCDFetchFeed · GitHub

CPU:

​ 1、使用 Energy Log 检查 CPU 耗电,前台三分钟或者后台一分钟 CPU 线程连续占用80%以上判定为耗电,同事记录耗电线程堆栈供分析。
​ 2、查看线程情况,task_theadsact_list 数组包含所有线程,使用 thread_info 的接口可以返回线程的基本信息 thread_basic_info_t

内存:

​ 1、查看 APP 内存真实使用情况,webkit/MemoryFootprintCocoa.cpp
​ 2、JetSam 会判断 APP 内存使用情况,超出阈值就会杀死APP。
​ 3、NSProcessInfophysicalMemory 表示设备物理内存大小。

网络:

​ 1、使用 Fishhook hook 网络底层库 CFNetwork
​ 2、指标:DNS 时间,SSL 时间,首包时间,响应时间。

I/O:

​ 1、使用 Frida,动态二进制插桩技术,在程序运行时区插入自定义代码获取 I/O 的耗时和处理数据大小等数据。
​ 2、WWDC。

延后任务管理

对于分析后,没必要在启动阶段执行的方法,可以延后执行。一般创建四个队列:
• 异步串行队列:执行有依赖关系的任务。
• 异步并行队列:分组执行独立任务,限制任务数量,避免CPU和内存瞬时激增影响主线程用户操作。
• 闲时主线程串行队列:监听主线程 runloop 状态,在 kCFRunLoopBeforeWaiting 时开始执行闲时队列里的任务,在 kCFRunLoopAfterWaiting 是停止。
• 闲时异步串行队列:同上。

优化后如何保持

监控启动阶段方法耗时,出现异常快速定位。
通过 JSON 表示监控数据,自动化分析和定位。

2019.12.10

CLLocationManager 请求权限需要被强引用。

2019.12.19

iOS 项目架构

小团队

MVC
MVP
MVVM
MVCS

大团队

需要考虑如何划分模块粒度、如何分层、如何团队协作。

划分模块粒度

首先,模块划分需要遵循规范、清晰的原则。
其次,SOLID 原则。

  1. 单一功能原则:对象功能要单一,不要在一个对象里添加很多功能。
  2. 开闭原则:扩展是开放的,修改是封闭的。
  3. 里氏替换原则:子类对象是可以替代基类对象的。
  4. 接口隔离原则:接口的用途要单一,不要在一个接口上根据不同的参数实现多个功能。
  5. 依赖反转原则:方法应该依赖抽象,不要依赖实例。iOS 开发就是高层业务方法依赖于协议。 最后,选择合适的粒度。iOS 组件,应该是包含 UI 控件,相关多个小功能的合集,是一种粒度适中的模块。

先按物理划分为不同的pod库,然后梳理组件之间的逻辑关系,进行改造。

组件分层:
1. 底层是与业务无关的基础组件,比如网络和存储等; 2. 中间层是通用的业务组件,比如账号、埋点、支付、购物车等; 3. 最上层是迭代业务组件,更新频率最高。

被多个业务或团队使用的功能模块才需要做成组件。

多团队分工

首先,基建团队,负责业务无关的基础功能组件和业务相关的通用业务组件。
然后,业务团队,耦合度高的业务可以划分成单独的业务团队。
最后,人员相互流动,相互了解。

理想的架构

协议式架构:采用协议式编程思路,在编译层使用协议定义规范,实现可在不同地方,从而达到分布管理和维护组件的目的。
缺点:缺少统一调度层,导致难于集中管理;协议过于规范,不够灵活。

中间者架构:采用中间者统一管理的方式,来控制APP的整个生命周期中组件的调用关系。组件接口设计要保持一致。
CTMediator,运行时解耦。

2019.12.31

使用 lame 库,实现 pcm 流 转 mp3 流。

Comments