NSTimer 是 iOS 和 macOS 开发中常用的定时器类,用于在指定的时间间隔后执行某个任务。它可以用来执行一次性任务或重复性任务。以下是 NSTimer 的基本用法和常见场景。
1. 创建 NSTimer
NSTimer 提供了多种创建方式,可以根据需求选择合适的方式。
1.1 使用 scheduledTimerWithTimeInterval:target:selector:userInfo:repeats: 方法
这是最常用的方式之一,它会自动将定时器添加到当前的运行循环中。
// 创建一个定时器,每隔1秒调用一次 target 的 selector 方法
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:1.0
target:self
selector:@selector(timerFired:)
userInfo:nil
repeats:YES];
-
timeInterval: 定时器触发的时间间隔(以秒为单位)。 -
target: 定时器触发时调用方法的对象。 -
selector: 定时器触发时调用的方法。 -
userInfo: 可选的用户信息,可以传递给定时器。 -
repeats: 是否重复触发。如果为YES,定时器会重复触发;如果为NO,定时器只触发一次。
1.2 使用 timerWithTimeInterval:target:selector:userInfo:repeats: 方法
这种方式不会自动将定时器添加到运行循环中,你需要手动将其添加到运行循环。
NSTimer *timer = [NSTimer timerWithTimeInterval:1.0
target:self
selector:@selector(timerFired:)
userInfo:nil
repeats:YES];
// 手动将定时器添加到当前运行循环
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];
1.3 使用 scheduledTimerWithTimeInterval:invocation:repeats: 方法
这种方式使用 NSInvocation 对象来指定要调用的方法。
NSMethodSignature *signature = [self methodSignatureForSelector:@selector(timerFired:)];
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
[invocation setTarget:self];
[invocation setSelector:@selector(timerFired:)];
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:1.0
invocation:invocation
repeats:YES];
1.4 使用 scheduledTimerWithTimeInterval:block:repeats: 方法(iOS 10+)
从 iOS 10 开始,NSTimer 提供了基于 block 的 API,使得代码更加简洁。
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:1.0
repeats:YES
block:^(NSTimer * _Nonnull timer) {
NSLog(@"定时器触发");
}];
2. 停止定时器
可以通过调用 invalidate 方法来停止定时器并将其从运行循环中移除。
[timer invalidate];
一旦调用了 invalidate,定时器将不再触发,并且不能再重新启动。如果你需要重新启动定时器,必须创建一个新的 NSTimer 实例。
3. 定时器触发的方法
定时器触发时会调用指定的 selector 或 block。如果是 selector 方式,方法签名必须符合以下格式:
- (void)timerFired:(NSTimer *)timer {
NSLog(@"定时器触发");
}
4. 注意事项
-
线程问题:
NSTimer默认会在创建它的线程的运行循环中运行。如果你在后台线程中创建了定时器,确保该线程的运行循环正在运行,否则定时器不会触发。 -
内存管理: 如果
NSTimer持有对target的强引用,可能会导致循环引用。为了避免这种情况,可以使用弱引用或者在适当的时候调用invalidate来释放定时器。 -
精确性:
NSTimer并不是绝对精确的,尤其是在主线程上运行时,可能会受到其他任务的影响。如果需要高精度的定时器,可以考虑使用CADisplayLink或 GCD 的dispatch_source_t。
5. 示例代码
#import <Foundation/Foundation.h>
@interface MyClass : NSObject
@property (nonatomic, strong) NSTimer *timer;
- (void)startTimer;
- (void)stopTimer;
- (void)timerFired:(NSTimer *)timer;
@end
@implementation MyClass
- (void)startTimer {
self.timer = [NSTimer scheduledTimerWithTimeInterval:1.0
target:self
selector:@selector(timerFired:)
userInfo:nil
repeats:YES];
}
- (void)stopTimer {
[self.timer invalidate];
self.timer = nil;
}
- (void)timerFired:(NSTimer *)timer {
NSLog(@"定时器触发 %@", timer.userInfo);
}
@end
int main(int argc, const char * argv[]) {
@autoreleasepool {
MyClass *myClass = [[MyClass alloc] init];
[myClass startTimer];
// 让程序运行一段时间
[[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:5]];
[myClass stopTimer];
}
return 0;
}
总结
NSTimer 是一个非常有用的工具,适合用于定时任务。你可以根据需求选择不同的创建方式,并注意定时器的生命周期管理和线程问题。











网友评论