NSTimer 的最小有效时间间隔是多少?
What's the minimum valid time interval of an NSTimer?
我想用NSTimer
增加标签上显示的数字。
这是我的代码:
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.numberLabel = [[UILabel alloc]initWithFrame:CGRectMake(90, 90, 90, 30)];
[self.view addSubview:self.numberLabel];
self.timer = [NSTimer scheduledTimerWithTimeInterval:0.01 target:self selector:@selector(refreshText) userInfo:nil repeats:YES];
[[NSRunLoop currentRunLoop]addTimer:self.timer forMode:NSRunLoopCommonModes];
}
- (void)refreshText{
NSDate *beginDate = [NSDate date];
static NSInteger a = 0;
a ++;
self.numberLabel.text = [NSString stringWithFormat:@"%ld",a];
if (a == 1000) {
NSDate *endDate = [NSDate date];
NSTimeInterval durationTime = [endDate timeIntervalSinceDate:beginDate];
NSTimeInterval intervalTime = self.timer.timeInterval;
NSLog(@"durationTime = %f",durationTime);
NSLog(@"intervalTime = %f",intervalTime);
[self.timer invalidate];
self.timer = nil;
}
}
控制台显示:
然后我把定时器的timeInterval从0.01改成0.001,控制台显示:
迷惑的是为什么timeInterval为0时durationTime不是0.0000056。001.What另外,NSTimer的timeInterval有没有最小值可以设置?
NSTimer
的时间段是 NSTimeInterval
类型的值,而这提供了 sub-millisecond precision that does not help you. From the start of the NSTimer
documentation:
Timers work in conjunction with run loops. Run loops maintain strong references to their timers, so you don’t have to maintain your own strong reference to a timer after you have added it to a run loop.
To use a timer effectively, you should be aware of how run loops operate. See Threading Programming Guide for more information.
A timer is not a real-time mechanism. If a timer’s firing time occurs during a long run loop callout or while the run loop is in a mode that isn't monitoring the timer, the timer doesn't fire until the next time the run loop checks the timer. Therefore, the actual time at which a timer fires can be significantly later. See also Timer Tolerance.
因此 NSTimer
的最小时间间隔与 运行 循环迭代的长度相关。虽然内部优化(如果存在)可以在设置后立即触发计时器,但如果间隔真的很小,一般来说,您将获得的最短时间取决于 运行 循环迭代的剩余执行时间设置了哪个定时器,这对于通用编程来说几乎是不确定的。
如果您真的需要高分辨率计时器(请参阅@bbum 对您的问题的评论),那么您需要研究该主题 - 只需搜索“高分辨率”之类的内容timing macOS”作为起点。
HTH
有更好的方法来解决您的问题。使用 CADisplayLink 而不是 NSTimer。 CADisplayLink 允许您在每次屏幕刷新时更新 UI - 尽可能快。更新 UI 频率超过屏幕刷新频率是没有意义的,因此 NSTimer 不是快速 UI 更新的最佳工具。
func beginUpdates() {
self.displayLink = CADisplayLink(target: self, selector: #selector(tick))
displaylink.add(to: .current, forMode: .defaultRunLoopMode)
}
func tick() {
// update label
}
func endUpdates(){
self.displayLink.invalidate()
self.displayLink = nil
}
我想用NSTimer
增加标签上显示的数字。
这是我的代码:
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.numberLabel = [[UILabel alloc]initWithFrame:CGRectMake(90, 90, 90, 30)];
[self.view addSubview:self.numberLabel];
self.timer = [NSTimer scheduledTimerWithTimeInterval:0.01 target:self selector:@selector(refreshText) userInfo:nil repeats:YES];
[[NSRunLoop currentRunLoop]addTimer:self.timer forMode:NSRunLoopCommonModes];
}
- (void)refreshText{
NSDate *beginDate = [NSDate date];
static NSInteger a = 0;
a ++;
self.numberLabel.text = [NSString stringWithFormat:@"%ld",a];
if (a == 1000) {
NSDate *endDate = [NSDate date];
NSTimeInterval durationTime = [endDate timeIntervalSinceDate:beginDate];
NSTimeInterval intervalTime = self.timer.timeInterval;
NSLog(@"durationTime = %f",durationTime);
NSLog(@"intervalTime = %f",intervalTime);
[self.timer invalidate];
self.timer = nil;
}
}
控制台显示:
然后我把定时器的timeInterval从0.01改成0.001,控制台显示:
迷惑的是为什么timeInterval为0时durationTime不是0.0000056。001.What另外,NSTimer的timeInterval有没有最小值可以设置?
NSTimer
的时间段是 NSTimeInterval
类型的值,而这提供了 sub-millisecond precision that does not help you. From the start of the NSTimer
documentation:
Timers work in conjunction with run loops. Run loops maintain strong references to their timers, so you don’t have to maintain your own strong reference to a timer after you have added it to a run loop.
To use a timer effectively, you should be aware of how run loops operate. See Threading Programming Guide for more information.
A timer is not a real-time mechanism. If a timer’s firing time occurs during a long run loop callout or while the run loop is in a mode that isn't monitoring the timer, the timer doesn't fire until the next time the run loop checks the timer. Therefore, the actual time at which a timer fires can be significantly later. See also Timer Tolerance.
因此 NSTimer
的最小时间间隔与 运行 循环迭代的长度相关。虽然内部优化(如果存在)可以在设置后立即触发计时器,但如果间隔真的很小,一般来说,您将获得的最短时间取决于 运行 循环迭代的剩余执行时间设置了哪个定时器,这对于通用编程来说几乎是不确定的。
如果您真的需要高分辨率计时器(请参阅@bbum 对您的问题的评论),那么您需要研究该主题 - 只需搜索“高分辨率”之类的内容timing macOS”作为起点。
HTH
有更好的方法来解决您的问题。使用 CADisplayLink 而不是 NSTimer。 CADisplayLink 允许您在每次屏幕刷新时更新 UI - 尽可能快。更新 UI 频率超过屏幕刷新频率是没有意义的,因此 NSTimer 不是快速 UI 更新的最佳工具。
func beginUpdates() {
self.displayLink = CADisplayLink(target: self, selector: #selector(tick))
displaylink.add(to: .current, forMode: .defaultRunLoopMode)
}
func tick() {
// update label
}
func endUpdates(){
self.displayLink.invalidate()
self.displayLink = nil
}