performSelector && NSTimer
使用performSelector系列的方法就是对NSTimer的一种封装,所以NSTimer需要注意的地方,就是performSelector需要注意的地方。
一般可以使用
[self performSelector:@selector(showAlertView) withObject:nil afterDelay:5];
但是要注意这个系列还有一个方法
- (void)performSelector:(SEL)aSelector withObject:(nullable id)anArgument afterDelay:(NSTimeInterval)delay inModes:(NSArray<NSRunLoopMode> *)modes;
对NSTimer而言,默认是在NSDefaultRunLoopMode模式下面执行,如果系统切到了其他的mode,比如说滑动一个scrollView,那么timer会等待,直到系统回到NSDefaultRunLoopMode模式下面。如果你的本意是不管怎么样,N秒后触发timer,那么必须要修改timer执行的mode。
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
否则,触发时间会在停止滑动scrollView后的某一个时间,中间的偏差就看你滑了多久的scrollView。
另外需要注意的地方是,一个线程如果没有开启Runloop, NSTimer会不生效。
dispatch_after
dispatch_after就好多了,不依赖于Runloop,但是没法取消。建议不需要取消的时候,都使用dispatch_after。
GCD Dispatch Source Timer
是用GCD timer也是可以的,但是有个问题就是首次触发时间貌似没法直接控制,dispatch_resume之后就立即执行了第一次。
self.timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_main_queue());
dispatch_source_set_timer(self.timer, DISPATCH_TIME_NOW,5 * NSEC_PER_SEC, 0.1 * NSEC_PER_SEC);
dispatch_source_set_event_handler(self.timer, ^{
[self showAlertView];
});
dispatch_resume(self.timer);
注意持有dispatch_source_t对象。