更新标签在后台运行的计时器

时间:2013-04-28 09:48:18

标签: ios objective-c xcode nstimer

我使用更新标签的NSTimer编写了一个计时器。问题是在同一个viewcontroller中我有一个uitableview,当我向下滚动时,计时器不会更新它的值,所以用户可以“作弊”来停止计时器。

我认为使用CGD的串行队列可以很容易地解决这个问题,但我不知道该怎么做。

提前致谢,

4 个答案:

答案 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)