一款监控子线程操纵 UI 的能力,也能够增加自定义的 API 进行监控(实现在子线程监控某些 API 的时候捕捉具体堆栈信息,帮忙定位问题)
背景介绍
可能有些人始终没有遇到过因为在子线程操作 UI,导致在开发阶段 Xcode console 输入了一堆日志,大体如下
其实咱们能够给 Xcode 打个 Runtime Issue Breakpoint
,type 抉择 Main Thread Checker
, 在产生子线程操作 UI 的时候就会被零碎检测到并触发断点,同时能够看到堆栈状况
成果如下
问题及解决方案
上述的性能是在 Xcode 自带的,连贯 Xcode 做调试才具备的性能,线上包无奈检测到。
通过摸索 Xcode 实现该性能是依赖于设施上的 libMainThreadChecker.dylib
库,咱们能够通过 dlopen
办法强制加载该库让非 Xcode 环境下也领有监测性能。
另外在监控到子线程调用 UI 调用时,在 Xcode 环境下,会将调用栈输入到控制台,通过测试,libMainThreadChecker.dylib
应用的是进行输入的,因为 NSLog 是将信息输入到 STDERR
中,咱们能够通过 NSPipe
与 dup2
将 STDERR
输入拦挡,通过对信息的文案的判断,进而获取监测到的 UI 调用,最初能够通过堆栈打印进去,就能够帮忙定位到具体问题。
libMainThreadChecker.dylib
库具备局限性,仅仅对系统提供的一些特定类的特定 API 在子线程调用会被监控到(例如 UIKit 框架中 UIView 类)。
然而某些类有些 API 咱们也不心愿在子线程被调用,这时候 libMainThreadChecker.dylib
是无奈满足的。
对 libMainThreadChecker.dylib
库的汇编代码钻研,发现 libMainThreadChecker.dylib
是通过外部 __main_thread_add_check_for_selector
这个办法来进行类和办法的注册的。所以如果咱们同样能够通过 dlsym
来调用该办法,以达到对自定义类和办法的主线程调用监测。
另外该性能能够在线下 debug 阶段开启,判断是否是在 Xcode debug 状态,能够通过苹果提供的官网判断办法实现。
对 dlopen、dlsym 生疏的小伙伴能够间接看 Apple 官网文档,这里不做开展。
APM 合集
对于 APM 感兴趣的小伙伴能够查看这篇带你打造一套 APM 监控零碎的文章