NSTimer必知必会

1.不知道大家有没有注意,为什么NSTImer的property里是weak的?


首先,介绍一下单次定时和循环定时:

//创建一个类

@interface TestObj :NSObject

- (void)timerAct;

@end


@implementation TestObj

- (id)init

{

   self = [superinit];

    NSLog(@"Obj has been created!");;

    return self;

}

- (void)timerAct

{

    NSLog(@"timer is executing!");

}

- (void)dealloc

{

     NSLog(@"Obj has been dealloced!!");

    //[super  dealloc];

}

@end


//viewcontoller进行进行测试

- (void)viewDidLoad

{

    [superviewDidLoad];  

    [selfnonRepeatTimer];

    [selfRepeatTimer];

}


- (void)nonRepeatTimer//只执行一次的Timer

{

     NSLog(@"timer is nonRepeatTimer!");

    

   TestObj *test = [[TestObjalloc]init];

    [NSTimerscheduledTimerWithTimeInterval:5target:test selector:@selector(timerAct)userInfo:NULLrepeats:NO];

    //[test release];

    NSLog(@"Invoke release to testObject");

}


- (void)RepeatTimer//循环执行的Timer

{

    NSLog(@"timer is RepeatTimer!");

    

   TestObj *test = [[TestObjalloc]init];

    [NSTimerscheduledTimerWithTimeInterval:5target:test selector:@selector(timerAct)userInfo:NULLrepeats:YES];

    //[test release];

    NSLog(@"Invoke release to testObject");

}


执行一次Timer时的结果

2014-09-19 15:23:16.765 TEST[1760:60b] timer is nonRepeatTimer!

2014-09-19 15:23:16.767 TEST[1760:60b] Obj has been created!

2014-09-19 15:23:16.768 TEST[1760:60b] Invoke release to testObject

2014-09-19 15:23:21.769 TEST[1760:60b] timer is executing!

2014-09-19 15:23:21.770 TEST[1760:60b] Obj has been 


通过观察后两条语句得出结论:在间隔5秒以后执行timer的selector,执行完后立即释放testObj


执行循环Timer时的结果

2014-09-19 15:25:45.057 TEST[1777:60b] timer is RepeatTimer!

2014-09-19 15:25:45.059 TEST[1777:60b] Obj has been created!

2014-09-19 15:25:45.059 TEST[1777:60b] Invoke release to testObject

2014-09-19 15:25:50.060 TEST[1777:60b] timer is executing!

2014-09-19 15:25:55.060 TEST[1777:60b] timer is executing!


通过观察得出结论:每5秒执行一次timer的selector,但是对象一直没有释放。

而NSTimer的属性之所以为weak,原因真是在此:如果timer循环触发时,对象一直retain,那么将无法被创建它的类释放,因为timer使它的引用计数又加了1.



2.NSTimer是不是一定准时触发事件?


答案使否定的,当NSTimer被设置以后,会被丢到runloop中,达到触发时间时,如果此时runloop空闲就会立即执行;但是如果此时runloop正忙,则需要在触发时间的基础上等到runloop空闲再去执行。



3.为什么要把NSTimer添加到runloop才有用?


首先测试如果不放入runloop时:

- (void)viewDidLoad

{

    [superviewDidLoad];

    //[self nonRepeatTimer];

    //[self RepeatTimer];

    [selfnotPutInRunloop];

}

- (void)notPutInRunloop

{

    NSLog(@"timer don't put in runloop");

    

    NSTimer *timer = [[NSTimeralloc] initWithFireDate:[[NSDate alloc] initWithTimeIntervalSinceNow:5]interval:5target:selfselector:@selector(timerAct)userInfo:NULLrepeats:NO];//初始化一个新的NSTimer

    NSLog(@"Invoke release to testObject");

}

输出结果:

2014-09-19 16:34:06.005 TEST[2347:60b] timer don't put in runloop

2014-09-19 16:34:06.007 TEST[2347:60b] Obj has been created!

2014-09-19 16:34:06.008 TEST[2347:60b] Invoke release to testObject

2014-09-19 16:34:06.008 TEST[2347:60b] Obj has been dealloced!!

说明timer根本没有触发,因为这个次没有把timer放到runloop上。



4.如何把NSTimer添加到runloop中?


- (void)viewDidLoad

{

    [superviewDidLoad];

    //[self nonRepeatTimer];

    //[self RepeatTimer];

    //[self notPutInRunloop];

[NSThreaddetachNewThreadSelector:@selector(PutInRunloop)toTarget:selfwithObject:nil];//直接创建线程并运行,selector:线程执行的方法,target:selector消息发送的对象

}


- (void)PutInRunloop

{

    NSLog(@"timer  put in runloop");

    

   TestObj *test = [[TestObjalloc]init];

    NSTimer *timer  = [[NSTimeralloc] initWithFireDate:[[NSDatealloc] initWithTimeIntervalSinceNow:5]interval:5target:selfselector:@selector(timerAct)userInfo:NULLrepeats:NO];

    [[NSRunLoopcurrentRunLoop] addTimer:timerforMode:NSDefaultRunLoopMode];

    NSLog(@"Invoke release to testObject");

}

输出的结果:

2014-09-19 16:28:36.480 TEST[2227:3307] timer  put in runloop

2014-09-19 16:28:36.483 TEST[2227:3307] Obj has been created!

2014-09-19 16:28:36.485 TEST[2227:3307] Invoke release to testObject

2014-09-19 16:28:36.486 TEST[2227:3307] Obj has been dealloced!!


还是没有执行方法,why?

- (void)PutInRunloop

{

    NSLog(@"timer  put in runloop");

    

   TestObj *test = [[TestObjalloc]init];

    NSTimer *timer  = [[NSTimeralloc] initWithFireDate:[[NSDatealloc] initWithTimeIntervalSinceNow:5]interval:1target:test selector:@selector(timerAct)userInfo:NULLrepeats:NO];

    [[NSRunLoopcurrentRunLoop] addTimer:timerforMode:NSDefaultRunLoopMode];

    [[NSRunLoopcurrentRunLoop] runUntilDate:[NSDatedateWithTimeIntervalSinceNow:5]]; //这里的NSData参数必须大于上面NSTimer初始化时开始的时间

    NSLog(@"Invoke release to testObject");

}

是因为[[NSRunLoop currentRunLooprunUntilDate:[NSDate dateWithTimeIntervalSinceNow:5]]没有加,这个代表该runloop将会在5秒以后结束;

通过子线程调用selector时,子线程是不会默认启动的,必须加上runUntilDate 方法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值