最近闲的没事看了一下定时器,那么就写下来,介绍一下定时器。
首先,说说定时器的应用场景:
1当我们需要反复间隔一段时间做的事情.
2当我们需要延时执行一些操作时候。(当然我们也可以使用
- (void)performSelector:(SEL)aSelector withObject:(id)anArgument afterDelay:(NSTimeInterval)delay inModes:(NSArray *)modes;
以上两种方式 都是类似原理;
我推荐使用 dispatch after来做,可以确保多线程下依然有效。(至于dispatch怎么做repeat多次操作,可以用递归实现。下面我回贴一下代码)
)
- (void)doSomething{
__weak yourController *weakSelf = self;
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
if (某条件成立) {
[weakSelf doSomething];
}
}
当然你如果需要了解timer可以去看看官方文档:https://developer.apple.com/library/ios/documentation/Cocoa/Reference/Foundation/Classes/NSTimer_Class/index.html#//apple_ref/doc/uid/TP40003747
以下是创建一个定时器方法,我会分别介绍,在介绍定时器使用之前,我会介绍一下定时器是如何工作的。定时器是基于runloop的,你创建的定时器必须是添加到runloop上才可以工作,你不必对他强持有,因为runloop已经做了这个事情。当合适的时候,就会触发,你也可以调用fire去立刻触发他.当然由于是基于runloop管理的,那么就会存在误差,比如我们在回调中处理一些耗时操作,活着是在不同的runloop mode模式下也会有影响。!那么你会问,万一控制器销毁了,timer依然调用控制器的方法,不就会造成crash。苹果也考虑到了这点,当我们新建一个timer时候,timer都会去对targer对象持有一份,以保证timer还活着的时候,控制器不会被销毁。
Creating a Timer
-
valid
Property -
fireDate
Property -
timeInterval
Property -
userInfo
Property
+(NSTimer *)kscheduledTimerWithTimeInterval:(NSTimeInterval)interval block:(void (^)())block repeats:(BOOL)repeats;
#import <Foundation/Foundation.h>
//接口部分
@interface NSTimer (CLBlockSupport)
+(NSTimer *)kscheduledTimerWithTimeInterval:(NSTimeInterval)interval block:(void(^)())block repeats:(BOOL)repeats;
@end
//实现部分
@implementation NSTimer (CLBlockSupport)
+(NSTimer *)kscheduledTimerWithTimeInterval:(NSTimeInterval)interval block:(void (^)())block repeats:(BOOL)repeats
{
return [self scheduledTimerWithTimeInterval:interval target:self selector:@selector(clblockInvoke:)userInfo:[block copy]repeats:repeats];
}
+(void)clblockInvoke:(NSTimer*)timer
{
void(^block)()=timer.userInfo;
if (block) {
block();
}
}
解释一下:这个办法如何能解决"保留环"的问题呢?通过代码可以看到,这段代码将计时器所应执行的任务封装成块,在调用计时器函数时,把他作为userinfo参数传进去.该参数可用来存放"万能值",只要计时器还有效,就会一直保留他.传入参数时要通过copy方法将block拷贝到"堆"上,否则等到稍后要执行它的时候,该块可能已经无效了.计时器现在的target是NSTimer类对象,这是一个单例,因此计时器是否会保留它,已经无所谓了.此处依然有保留环,但是因为类对象无须回收,所以不用担心.
注意:创建timer的时候,先定义一个弱(weak)引用,令其指向self,然后使Block捕获这个引用,而不是直接捕获普通的self变量,也就是说,self不会为计时器所保留.当Block开始执行时,立刻生成强(strong)引用,以保证实例在执行期间持续存活.下面是一个使用这个方法的例子:
__unsafe_unretained ClassA * weakView =self
timer = [NSTimerclscheduledTimerWithTimeInterval:1.0block:^{
ClassA * strongView = weakView;
[strongViewstartGo];
}repeats:YES];