看到这个标题,你可能会想NSTimer不就是计时器吗,谁不会用,不就是一个能够定时的完成任务的东西吗?
我想说你知道NSTimer会retain你添加调用方法的对象吗?你知道NSTimer是要加到runloop中才会起作用吗?你知道NSTimer会并不是准确的按照你指定的时间触发的吗?你知道NSTimer就算添加到runloop了也不一定会按照你想象中的那样执行吗?
如果上面提出的哪些问题,你并不全部了解,那么请细心的看完下面的文章,上面的那几个问题我会一一说明,并给出详细的例子。
一、什么是NSTimer
官方给出解释是“A timer provides a way to perform a delayed action or a periodic action. The timer waits until a certain time interval has elapsed and then fires, sending a specified message to a specified object. ” 翻译过来就是timer就是一个能在从现在开始的后面的某一个时刻或者周期性的执行我们指定的方法的对象。
二、NSTimer和它调用的函数对象间到底发生了什么
从前面官方给出的解释可以看出timer会在未来的某个时刻执行一次或者多次我们指定的方法,这也就牵扯出一个问题,如何保证timer在未来的某个时刻触发指定事件的时候,我们指定的方法是有效的呢?
解决方法很简单,只要将指定给timer的方法的接收者retain一份就搞定了,实际上系统也是这样做的。不管是重复性的timer还是一次性的timer都会对它的方法的接收者进行retain,这两种timer的区别在于“一次性的timer在完成调用以后会自动将自己invalidate,而重复的timer则将永生,直到你显示的invalidate它为止”。
下面我们看个小例子:
//
// TestObject.h
// NSTimerDemo
//
// Created by administrator on 13-6-24.
// Copyright (c) 2013年 enuola. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface TestObject : NSObject
//timer响应函数,只是用来做测试
-(void)timerAction:(NSTimer *)timer;
@end
//
// TestObject.m
// NSTimerDemo
//
// Created by administrator on 13-6-24.
// Copyright (c) 2013年 enuola. All rights reserved.
//
#import "TestObject.h"
@implementation TestObject
-(id)init
{
self = [super init];
if(self)
{
NSLog(@"instance %@ has been created!", self);
}
return self;
}
-(void)dealloc
{
NSLog(@"instance %@ has been dealloced!", self);
[super dealloc];
}
-(void)timerAction:(NSTimer *)timer
{
NSLog(@"Hi,Timer Action for instance %@", self);
}
@end
//调用上面定义的类,进行测试
// ViewController.m
// NSTimerDemo
//
// Created by administrator on 13-6-24.
// Copyright (c) 2013年 enuola. All rights reserved.
//
#import "ViewController.h"
#import "TestObject.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
//测试NSTimer是否会retain一个Object对象?答案:会
[self testNonRepeatTimer];
// [self testRepeatTimer];
}
//不循环的定时器测试方法
-(void)testNonRepeatTimer
{
NSLog(@"Test retain target for non-repeat");
TestObject *testObject = [[TestObject alloc] init];
[NSTimer scheduledTimerWithTimeInterval:5 target:testObject selector:@selector(timerAction:) userInfo:nil repeats:NO];
[testObject release];
NSLog(@"Invoke release to testObject");
}
//循环的定时器测试方法
-(void)testRepeatTimer
{
NSLog(@"Test retain target for repeat Timer");
TestObject *testObject2 = [[TestObject alloc] init];
[NSTimer scheduledTimerWithTimeInterval:5 target:testObject2 selector:@selector(timerAction:) userInfo:nil repeats:YES];
[testObject2 release];
NSLog(@"Invoke release to testObject2");
}