我使用更新标签的NSTimer编写了一个计时器。问题是在同一个viewcontroller中我有一个uitableview,当我向下滚动时,计时器不会更新它的值,所以用户可以“作弊”来停止计时器。
我认为使用CGD的串行队列可以很容易地解决这个问题,但我不知道该怎么做。
提前致谢,
涓
答案 0 :(得分:3)
首先请记住,除了主线程之外,您无法在任何其他线程中执行UI更改。话虽如此,您需要在主队列中触发NSTimer
,否则在更改UILabel
时程序将崩溃。请查看此链接http://bynomial.com/blog/?p=67和此链接http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSRunLoop_Class/Reference/Reference.html
据我所知,如果您在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!"];
}
答案 1 :(得分:0)
如果你在主线程中运行计时器而不是滚动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];
});}
答案 2 :(得分:0)
-(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];
答案 3 :(得分:0)
要更新用户界面,您需要使用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)