iOS开发中如何监控ANR
在 iOS 开发中,使用 Objective-C 监控 ANR(Application Not Responding)和卡顿,主要依靠监控主线程的响应能力。由于 iOS 没有明确的 ANR 定义像 Android 那样,通常情况下是监控主线程的阻塞时间来判断应用是否卡顿或无响应。
以下是一些常用的卡顿/ANR 监控和防治手段:
一、监控 ANR/卡顿
RunLoop 监控:
这是最常用的方法。RunLoop 负责处理 App 中的各种事件(例如用户输入、网络请求、定时器等)。通过监控 RunLoop 的状态,可以判断主线程是否卡顿。
原理: 在主线程 RunLoop 的每个循环开始和结束时记录时间戳。如果两次时间戳的差值超过预设的阈值(例如 5 秒),则认为发生了卡顿。
#import "ANRMonitor.h"
@interface ANRMonitor ()
@property (nonatomic, strong) CFRunLoopObserverRef observer;
@property (nonatomic, assign) CFRunLoopActivity activities;
@property (nonatomic, assign) NSTimeInterval lastRunLoopStartTime;
@end
@implementation ANRMonitor
+ (instancetype)sharedInstance {
static ANRMonitor *instance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
instance = [[ANRMonitor alloc] init];
});
return instance;
}
- (void)startMonitoring {
self.lastRunLoopStartTime = 0;
CFRunLoopObserverContext context = {0, (__bridge void*)self, NULL, NULL, NULL};
self.observer = CFRunLoopObserverCreate(kCFAllocatorDefault,
kCFRunLoopAllActivities,
YES,
0,
&runLoopObserverCallBack,
&context);
CFRunLoopAddObserver(CFRunLoopGetMain(), self.observer, kCFRunLoopCommonModes);
}
static void runLoopObserverCallBack(CFRunLoopObserverRef observer, CFRunLoopActivity activity, void *info) {
ANRMonitor *monitor = (__bridge ANRMonitor*)info;
monitor.activities = activity;
if (activity == kCFRunLoopBeforeSources || activity == kCFRunLoopAfterWaiting) {
monitor.lastRunLoopStartTime = CACurrentMediaTime();
} else if (activity == kCFRunLoopBeforeWaiting) {
NSTimeInterval currentTime = CACurrentMediaTime();
NSTimeInterval runLoopDuration = currentTime - monitor.lastRunLoopStartTime;
if (runLoopDuration > 5) { // 超过 5 秒视为卡顿
NSLog(@"Main thread stuck for %f seconds.", runLoopDuration);
// 可以在这里收集卡顿信息,例如堆栈、CPU 使用率等
}
}
}
- (void)stopMonitoring {
if (self.observer) {
CFRunLoopRemoveObserver(CFRunLoopGetMain(), self.observer, kCFRunLoopCommonModes);
CFRelease(self.observer);
self.observer = NULL;
}
}
@end
使用方法: 在 AppDelegate 的 application:didFinishLaunchingWithOptions: 方法中调用 [[ANRMonitor sharedInstance] startMonitoring]; 开始监控。
主线程 Ping:
创建一个子线程,定期向主线程发送消息。如果主线程在一定时间内没有响应消息,则认为主线程卡顿。
性能监控工具:
Instruments: Xcode 自带的 Instruments 工具可以用来分析 CPU 使用率、内存分配、图形渲染等性能指标,帮助定位卡顿原因。
第三方性能监控平台: 像是 Sentry 和 AppDynamics [2, 5]( https://docs.appdynamics.com/display/PRMY23/Customize+the+iOS+Instrumentation , https://docs.appdynamics.com/display/PRMY23/Instrument+an+iOS+Application) 等,可以收集崩溃报告、性能数据,并提供可视化的分析工具。
二、卡顿防治手段
避免在主线程执行耗时操作:
将耗时任务(例如网络请求、图片加载、复杂计算)放到子线程执行,完成后再回到主线程更新 UI。可以使用 GCD 或 NSOperationQueue 来管理子线程。
优化 UI 渲染:
减少视图层级,使用 Auto Layout 优化布局计算。
避免离屏渲染,尽量使用不透明视图。
使用预加载和缓存机制,减少不必要的计算和绘制。
优化数据处理:
使用合适的数据结构和算法,避免不必要的遍历和查找。
使用缓存机制,减少重复计算。
代码优化:
避免循环引用,及时释放不再使用的对象。
避免使用过多的锁,减少线程竞争。
总结:
监控 ANR/卡顿需要结合多种手段,才能更全面地了解应用的性能状况。选择合适的监控方案和防治手段,可以有效提升应用的流畅度和用户体验。
本文来自博客园,作者:CoderWGB,转载请注明原文链接:https://www.cnblogs.com/wgb1234/articles/18591501

浙公网安备 33010602011771号