Runloop的运用场景
定时器NSTimer
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(timerAction) userInfo:nil repeats:YES];
[[NSRunLoop mainRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];
这样写会有个问题,当屏幕有触摸事件时,该timer会卡住。什么原因?是线程卡住吗?其实不然,这就要说到另外一种模式:UITrackingRunLoopMode。看下图:
默认模式:NSDefaultRunLoopMode
UI模式:UITrackingRunLoopMode
当UI模式没有被触发时,默认模式中的Timer会被执行。但当UI模式有事件,会优先触发该模式下的Source,用户体验高于一切。知道原因,那么好办,将Timer添加到UI模式下即可。
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(timerAction) userInfo:nil repeats:YES];
[[NSRunLoop mainRunLoop] addTimer:timer forMode: UITrackingRunLoopMode];
但是,会出现另外一种情况,当UI没有事件触发时,timerAction不会每一秒执行。究其原因,UITrackingRunLoopMode虽然优先级高,但只能被触摸事件触发。那么我们可以这样写:
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(timerAction) userInfo:nil repeats:YES];
[[NSRunLoop mainRunLoop] addTimer:timer forMode: NSDefaultRunLoopMode];
[[NSRunLoop mainRunLoop] addTimer:timer forMode: UITrackingRunLoopMode];
确实,该代码不管UI有没有事件,timerAction都会每秒钟被调用。但怎么都觉得该代码有点奇怪,其实另一种mode可以包含该两种模式。即
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(timerAction) userInfo:nil repeats:YES];
[[NSRunLoop mainRunLoop] addTimer:timer forMode: NSRunLoopCommonModes];
这里顺便列一下NSRunloopMode
1. NSRunLoopCommonModes // 占位模式,包含UITrackingRunLoopMode、NSDefaultRunLoopMode,至于有没有其他模式,未知
2. NSDefaultRunLoopMode // 默认模式
3. NSEventTrackingRunLoopMode // 基本不使用
4. NSModalPanelRunLoopMode // 基本不使用
5. UITrackingRunLoopMode // UI模式
该文章为笔记记录,如有朋友看到,且发现不妥之处,欢迎留言指正。