我使用更新标签的 NSTimer 编写了一个计时器。问题是,在同一个视图控制器中,我有一个 uitableview,当我向下滚动它时,计时器不会更新它的值,因此用户可以“作弊”来停止计时器。
我认为这可以很容易地通过带有 CGD 的串行队列来解决,但我不知道该怎么做。
提前致谢,
胡安
我使用更新标签的 NSTimer 编写了一个计时器。问题是,在同一个视图控制器中,我有一个 uitableview,当我向下滚动它时,计时器不会更新它的值,因此用户可以“作弊”来停止计时器。
我认为这可以很容易地通过带有 CGD 的串行队列来解决,但我不知道该怎么做。
提前致谢,
胡安
首先请记住,除了主线程之外,您不能在任何其他线程中执行 UI 更改。话虽如此,您需要NSTimer
在主队列中触发,否则程序会在更改UILabel
. 看看这个链接http://bynomial.com/blog/?p=67和这个http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSRunLoop_Class/参考/Reference.html
据我所知,如果您在 for 中安排计时器,NSRunLoopCommonModes
它将忽略事件更新并按照您的需要触发计时器:
NSTimer *timer = [NSTimer timerWithTimeInterval:1.0
target:self
selector:@selector(timerDidTick:)
userInfo:nil repeats:YES];
[[NSRunLoop mainRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
-(void) timerDidTick:(NSTimer*) theTimer{
[[self myLabel] setText:@"Timer ticked!"];
}
如果您在主线程中运行计时器而不是滚动 tableview 其停止计时器时,我遇到了同样的问题。解决方案是您在后台运行计时器并在主线程中更新 GUI
UIApplication *app = [UIApplication sharedApplication];
__block UIBackgroundTaskIdentifier bgTask = [app beginBackgroundTaskWithExpirationHandler:^{
[app endBackgroundTask:bgTask];
bgTask = UIBackgroundTaskInvalid;
}];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
//run function methodRunAfterBackground
updateTimer1=[NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(updateGUIAudioPlayer) userInfo:nil repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:updateTimer1 forMode:NSDefaultRunLoopMode];
[[NSRunLoop currentRunLoop] run];
});
-(void)updateGUIAudioPlayer {
dispatch_async(dispatch_get_main_queue(), ^{
self.label.text = @"your text";
});
//but if you want to stop timer by himself than use main thread too like that
dispatch_async(dispatch_get_main_queue(), ^{
[updateTimer1 invalidate];
});}
-(void) timerDidTick:(NSTimer*) theTimer{
_currentNumber =_currentNumber+1;
//check if current number is bigger than the contents of the word array
if (_currentNumber <=wordArray.count-1) {
NSLog(@"_currentNumber @%i wordArray @%i",_currentNumber,wordArray.count);
_RandomLoadingText.text = @"Timer" ;
[self changeTextInRandomLoadingLabel:_currentNumber];
}
else if (_currentNumber >=wordArray.count-1)
{
NSLog(@"reached end of array");
[timer invalidate];
}
}
-(void)changeTextInRandomLoadingLabel:(int)myInt
{
_RandomLoadingText.text = [wordArray objectAtIndex:myInt];
}
//--------- 视图已加载
_RandomLoadingText.text = @"Test";
_currentNumber =0;
timer = [NSTimer timerWithTimeInterval:1.0
target:self
selector:@selector(timerDidTick:)
userInfo:nil repeats:YES];
[[NSRunLoop mainRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
要更新 UI,您需要使用OperationQueue.main
. 假设你有一个UILabel
命名的 timeLabel:
var timeInSeconds = 0
timer = Timer(timeInterval: 1, repeats: true, block: { timer in
timeInSeconds += 1
OperationQueue.main.addOperation {
self.timeLabel.text = String(timeInSeconds)
}
})
RunLoop.main.add(timer, forMode: .commonModes)