一款监控子线程操纵 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 监控零碎的文章