MTHawkeye 源码学习
一、简介
MTHawkeye 是美图 iOS 团队开源的一款调试辅助、性能优化辅助工具集,旨在帮助 iOS 开发者提升开发效率、辅助优化性能体验,是 iOS 开发者非常值得引入和学习的开源工具。
本文意在通过分析 MTHawkeye 的源码实现,帮助学习 iOS 开发技术及原理。
本文所分析的源码为 MTHawkeye 仓库 develop 分支 [4e2af4d](https://github.com/yujiuqie/MTHawkeye) 提交,不同递交代码可能存在部分差异。
二、工程结构
MTHawkeye 核心代码位于 MTHawkeye/MTHawkeye/ 文件夹,包含 Core、DefaultPlugins、EnergyPlugins、FLEXExtension、GraphicsPlugins、MemoryPlugins、NetworkPlugins、StackBacktrace、StorageMonitorPlugins、TimeConsumingPlugins、UISkeleton、Utils 12 个子文件夹。
MTHawkeye 通过这 12 个子文件夹中的代码完成包括性能监测、内存监测、网络监测、CPU监测、沙盒存储、图形监测以及 FLEX 扩展等服务。
文件夹 | 功能 |
---|---|
TimeConsumingPlugins | |
MemoryPlugins | |
NetworkPlugins | |
EnergyPlugins | |
StorageMonitorPlugins | |
GraphicsPlugins | |
FLEXExtension | |
Core | |
DefaultPlugins | |
StackBacktrace | |
Utils | |
UISkeleton |
接下来我们通过源码来分析这些功能的技术实现。
三、技术实现
3.1 Core 文件夹
Core 文件夹包含以下文件
文件 | 功能 |
---|---|
MTHawkeyePlugin | 插件协议,MTHawkeye 默认插件及扩展插件都必须遵循该协议 |
MTHawkeyeAppStat | |
MTHawkeyeAverageStorage | |
MTHawkeyeClient | |
MTHawkeyeDyldImagesStorage | |
MTHawkeyeStorage |
3.1.1 MTHawkeyeUserDefaults
MTHawkeyeUserDefaults 是一个工具类,支持单例实现,主要实现对特定 key-value 的存储及监听回调,它的结构及核心方法描述如图:
名称 | MTHawkeyeUserDefaults |
---|---|
类型 | 工具类 |
作用 | 实现了一套更加易于使用的 KVO 功能,对字段的监听更方便,被监听的值可以实时离线保存 |
源码分析和学习主要关注以下四个部分:
- 核心方法 1
- 核心方法 2
- UserDefaults 监听及回调的管理
- UserDefaults 离线存储
核心方法 1:针对 object 对象的 key 值执行监听,如果 key 值发生变化,则回调 handler
1 | - (void)mth_addObserver:(NSObject *)object forKey:(NSString *)key withHandler:(MTHawkeyeUserDefaultChangedHandler)handler { |
核心方法 2: 对指定 key 的 value 进行更新,会触发核心方法 1 中的 handler 回调,此方法内部实现未区分核心方法 1 中的 object 维度,因此所有监听了同样 key 的 object 对象均会回调 handler 方法
1 | - (void)setObject:(nullable id)value forKey:(NSString *)defaultName { |
UserDefaults 监听及回调的管理:
监听对象和 key 以及 handler 通过 MTHUserDefaultsObserverInfo 类进行关联和管理,该类仅用于 MTHawkeyeUserDefaults 中
UserDefaults 离线存储:
通过 MTHawkeyeUserDefaults 存储的值会通过 [MTHawkeyeUtility hawkeyeStoreDirectory] 写入离线文件 preferences 中
1 | - (NSString *)cachePath { |
3.1.2 MTHawkeyeStorage
MTHawkeyeStorage 官方介绍参考 hawkeye-storage-cn.md
四、存在问题
异常报错
1 | Cannot initialize a parameter of type 'id<NSCopying> _Nonnull' with an rvalue of type 'Class' |
解决方案:GitHub -