RunLoop & NSTimer 结合使用.md

NSTimer有两种类型的初始化方法, 一种是scheduledTimerWithXXX, 一种是timerWithXXX.

scheduledTimerWithXXX:
Creates and returns a new NSTimer object and schedules it on the current run loop in the default mode.
自动添加到RunLoop中.

这一种方法只能在主线程中使用, 不需要调用fire函数, 也不能通过NSRunLoopaddTimer函数添加, 因为它会被自动添加到当前的RunLoop中.
例如下面的写法, 定时函数是不会调用的, 即使把addTimer那一行代码注释掉也不能正常调用定时函数.

__weak __typeof(&*self) weakself = self;
dispatch_async(dispatch_get_global_queue(0, 0), ^{
    weakself.timer = [NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:@selector(timerFired) userInfo:nil repeats:YES];
    [[NSRunLoop mainRunLoop] addTimer:weakself.timer forMode:NSRunLoopCommonModes];
});

要想正常运行,只需要把scheduledTimerWithXXX换成timerWithXXX即可.

timerWithXXX:
Creates and returns a new NSTimer object initialized with the specified object and selector.
初始化NSTimer, 需要手动添加到RunLoop中.

当在主线程中初始化时, 如下代码:

self.timer = [NSTimer timerWithTimeInterval:2.0 target:self selector:@selector(timerFired) userInfo:nil repeats:YES];
[self.timer fire];

需要调用fire函数才能触发. 而且不管repeatsYES还是NO, 都只触发一次定时函数.
正确的使用范例如下:

__weak __typeof(&*self) weakself = self;
dispatch_async(dispatch_get_global_queue(0, 0), ^{
    weakself.timer = [NSTimer timerWithTimeInterval:2.0 target:self selector:@selector(timerFired) userInfo:nil repeats:YES];
    [[NSRunLoop currentRunLoop] addTimer:weakself.timer forMode:NSDefaultRunLoopMode];
    [[NSRunLoop currentRunLoop] run]; // 这一句不能少, 是为了保持线程运行
});```
> 摘自: [www.cnblogs.com/liyang31tg/p/3662557.html](http://www.cnblogs.com/liyang31tg/p/3662557.html)
NSRunLoop的理解,每一个线程都有一个NSRunLoop对象,然而定时器也是在这个对象上面运行的,当一个线程运行完成了过后,会自动关闭线程,自然NSRunLoop也会被销毁,自然定时器就不会运行,为了不让其线程关闭,用此语句   [[NSRunLoop currentRunLoop] run]; 那么线程就会保持活跃状态(前提是这个线程里面还有需要被执行的东西,比如说定时器,网络请求等(经过测试的,网络请求,GCD也一样), (这可能是一种优化,单凭这句话,还不能将此线程保持活跃,必须有需要执行的东西),不会被关闭,自然定时器也就能用了.

你可能感兴趣的:(RunLoop & NSTimer 结合使用.md)