实现原理:开启子线程监控主线程的RunLoop的状态,并设定超时时间。如果发生了超时,而且此时RunLoop的状态为kCFRunLoopBeforeSources 或 kCFRunLoopAfterWaiting,认为主线程卡顿;
CFRunLoopObserverRef _runloopObserver;
dispatch_semaphore_t _semaphore;
NSInteger _timeOutCount;
CFRunLoopActivity _activity;
void runLoopObserverCallBack(CFRunLoopObserverRef observer, CFRunLoopActivity activity, void *info)
{
ViewController *vc = (__bridge ViewController *)info;
vc->_activity = activity;
switch (activity) {
case kCFRunLoopAfterWaiting:
NSLog(@"kCFRunLoopAfterWaiting");
break;
case kCFRunLoopBeforeSources:
NSLog(@"kCFRunLoopBeforeSources");
break;
case kCFRunLoopBeforeWaiting:
NSLog(@"kCFRunLoopBeforeWaiting");
break;
case kCFRunLoopBeforeTimers:
NSLog(@"kCFRunLoopBeforeTimers");
break;
default:
break;
}
dispatch_semaphore_t semaphore = vc->_semaphore;
dispatch_semaphore_signal(semaphore);
}
//开始监控
-(void)startMonitor
{
if(_runloopObserver){
return;
}
_semaphore = dispatch_semaphore_create(0);
CFRunLoopObserverContext context = {0, (__bridge void *)(self), NULL, NULL};
_runloopObserver = CFRunLoopObserverCreate(kCFAllocatorDefault, kCFRunLoopAllActivities, YES, 0, runLoopObserverCallBack, &context);
CFRunLoopAddObserver(CFRunLoopGetMain(), _runloopObserver, kCFRunLoopCommonModes);
//开启子线程循环监控
dispatch_async(dispatch_get_global_queue(0, 0), ^{
while (YES) {
dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, 3 * NSEC_PER_SEC);
long semaphoreWait = dispatch_semaphore_wait(_semaphore, time);
if(semaphoreWait != 0){ //超时
if(!_runloopObserver){
_timeOutCount = 0;
_semaphore = 0;
_activity = 0;
return;
}
if(_activity == kCFRunLoopAfterWaiting || _activity == kCFRunLoopBeforeSources){
NSLog(@"发现一次延时");
if(++_timeOutCount < 3){
continue;
}
}
}else{
_timeOutCount = 0;
}
}
});
}
完整的demo路径:https://github.com/xiaobai1315/MonitorMainQueue