【问题标题】:Implementing a Countdown Timer in Objective-c?在 Objective-c 中实现倒数计时器?
【发布时间】:2012-05-26 15:37:26
【问题描述】:

我是 iOS 编程新手。我正在开发单词匹配游戏。在这个游戏中,我需要实现显示分钟和秒的时间计数器。我希望我的游戏开始时我的计时器从 3 分钟开始。现在我想用秒数反向减少这个计时器。我的代码只工作了几秒钟。这是我的代码:

  secondsLeft--;

  int seconds = (secondsLeft %3600) % 60;

  Timerlbl.text = [NSString stringWithFormat:@"%02d",seconds];


  if (seconds==0)

{


 UIAlertView *pAlert = [[UIAlertView alloc]initWithTitle:@"Sorry!!"   
 message:@"TimeOver"        delegate:self    cancelButtonTitle:@"OK"   
 otherButtonTitles:@"Cancel",nil];

 [pAlert show];

[pAlert release];

 }

 }

在 Viewdidload 我通过计时器调用它..

          countDown=[NSTimer scheduledTimerWithTimeInterval:5.0 target:self 
                 selector:@selector(TimeOver) userInfo:nil repeats:YES];

请任何人指导我如何在几分钟和几秒钟内完成。

【问题讨论】:

标签: iphone objective-c ios nstimer


【解决方案1】:

Objective-C 中的代码简单且更少,

in .h file create objects for Timer and totalSeconds

 NSTimer *timer;
 int totalSeconds;

.m file
//you can call this method where you want 
[self startTimer];

-(void)startOtpTimer {
     totalSeconds = 120;//your time 
     timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self 
     selector:@selector(updateCountDownTime) userInfo:nil repeats:YES];
 }

-(void)updateCountDownTime {
    [self populateLabelwithTime:totalSeconds];
        if( totalSeconds != 0) {
            totalSeconds -= 1;
        } else {
              [timer invalidate];//stop timer
              self.timeLabel.text = @"";//after reach 0 you can set empty string
         }
}

- (void)populateLabelwithTime:(int)seconds {
    self.timeLabel.text = [NSString stringWithFormat:@"%02d", totalSeconds];
}

【讨论】:

  • 上帝,感谢互联网..我可以复制粘贴赚钱:)
【解决方案2】:

我知道这是个老问题,但我想分享我的实现方法。我们有方法 (timeIntervalSinceDate:) 来计算间隔并有固定的秒数来倒计时。在我的情况下是 300 秒。

2015 年 7 月 SWIFT 更新

@IBAction func startTimer(sender: UIButton) {
    sender.selected = !sender.selected;
    //if selected fire timer, otherwise stop
    if (sender.selected) {
        self.timer = NSTimer.scheduledTimerWithTimeInterval(0.1, target: self, selector: Selector("updateTimer"), userInfo: nil, repeats: true);
        self.startDate = NSDate();
    } else {
        self.stopTimer();
    }

}

func stopTimer() {
    self.timer.invalidate();
}

func updateTimer() {
    // Create date from the elapsed time
    var currentDate:NSDate = NSDate();
    var timeInterval:NSTimeInterval = currentDate.timeIntervalSinceDate(self.startDate!);

    //300 seconds count down
    var timeIntervalCountDown = 300 - timeInterval;
    var timerDate:NSDate = NSDate(timeIntervalSince1970: timeIntervalCountDown);

    // Create a date formatter
    var dateFormatter = NSDateFormatter();
    dateFormatter.dateFormat = "mm:ss";
    dateFormatter.timeZone = NSTimeZone(forSecondsFromGMT: 0);

    // Format the elapsed time and set it to the label
    var timeString = dateFormatter.stringFromDate(timerDate);
    self.timerLabel?.text = timeString;
}

Working github swift sample project

Objective-C

- (void)updateTimer
{
    // Create date from the elapsed time
    NSDate *currentDate = [NSDate date];
    NSTimeInterval timeInterval = [currentDate 
                                   timeIntervalSinceDate:self.startDate];
    NSLog(@"time interval %f",timeInterval);

    //300 seconds count down
    NSTimeInterval timeIntervalCountDown = 300 - timeInterval;

    NSDate *timerDate = [NSDate 
                         dateWithTimeIntervalSince1970:timeIntervalCountDown];

    // Create a date formatter
    NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
    [dateFormatter setDateFormat:@"mm:ss"];
    [dateFormatter setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0.0]];


    // Format the elapsed time and set it to the label
    NSString *timeString = [dateFormatter stringFromDate:timerDate];
    self.stopWatch.text = timeString;
}

- (void)stopTimer
{
    [self.stopWatchTimer invalidate];
    self.stopWatchTimer = nil;
    [self updateTimer];

}

- (void)startTimer
{

    if (self.stopWatchTimer) {
        [self.stopWatchTimer invalidate];
        self.stopWatchTimer = nil;
    }

    self.startDate = [NSDate date];    

    // Create the stop watch timer that fires every 100 ms
    self.stopWatchTimer = [NSTimer scheduledTimerWithTimeInterval:1.0/10.0
                                           target:self
                                         selector:@selector(updateTimer)
                                         userInfo:nil
                                          repeats:YES];
}

更新:

每次通过 updateTimer 时创建一个 NSDateFormatter 是非常昂贵的。在循环外创建 NSDateFormatter 并重用它要好得多。致谢:@siburb

【讨论】:

  • 如果有人要逐字复制/粘贴此内容(您知道自己是谁 - ?),每次通过 updateTimer 时创建 NSDateFormatter 的成本非常高。在循环外创建 NSDateFormatter 并重用它要好得多。
【解决方案3】:

你可以这样做(启用 ARC):-

@interface ViewController()
{
UILabel *progress;
    NSTimer *timer;
    int currMinute;
    int currSeconds;
}
@end


@implementation ViewController
- (void)viewDidLoad
{
    [super viewDidLoad];
    progress=[[UILabel alloc] initWithFrame:CGRectMake(80, 15, 100, 50)];
    progress.textColor=[UIColor redColor];
    [progress setText:@"Time : 3:00"];
    progress.backgroundColor=[UIColor clearColor];
    [self.view addSubview:progress];
    currMinute=3;
    currSeconds=00;

    // Do any additional setup after loading the view, typically from a nib.
}
-(void)start
{
    timer=[NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(timerFired) userInfo:nil repeats:YES];

}
-(void)timerFired
{
if((currMinute>0 || currSeconds>=0) && currMinute>=0)
{
    if(currSeconds==0)
    {
        currMinute-=1;
        currSeconds=59;
    }
    else if(currSeconds>0)
    {
        currSeconds-=1;
    }
    if(currMinute>-1)
    [progress setText:[NSString stringWithFormat:@"%@%d%@%02d",@"Time : ",currMinute,@":",currSeconds]];
}
    else
    {
        [timer invalidate];
    }
}

【讨论】:

  • 谢谢亲爱的@roronoa zorro,您的回答是我想要的最佳解决方案。
  • 嗨@roronoa-​​zorro,想知道如何处理暂停计时器?
  • 你不能暂停或重启定时器,你只能使其失效。暂停和恢复可以通过使用 NSDate 变量来复制,在你想要暂停的时候存储当前的 NSDate(实际上是无效的) & 从保存的 NSDate 对象重新启动计时器
  • 略显迂腐的评论:NSTimer 保留其目标,因此此代码将导致 ViewController 不会被释放,除非其计时器已达到零。有很多变通方法,主要涉及代理对象和弱引用,甚至没有必要真正重要——通常你有视图控制器,你知道无论如何都不会被释放(例如根视图控制器,通常)。
【解决方案4】:

在.h文件中

 IBOutlet UILabel* lblTimer;
 NSTimer* gameTimer;

在 .m 文件中

-(void)viewDidLoad 
{
    [super viewDidLoad];
    [self createTimer];
}

- (void)createTimer 
{       
     NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
     NSRunLoop* runLoop = [NSRunLoop currentRunLoop];

   gameTimer = [[NSTimer timerWithTimeInterval:1.00 target:self selector:@selector(timerFired:) userInfo:nil repeats:YES] retain];
   [[NSRunLoop currentRunLoop] addTimer:gameTimer forMode:NSDefaultRunLoopMode];
   timeCount = 20; 
   [runLoop run];
   [pool release];
}

- (void)timerFired:(NSTimer *)timer 
{
    if(timeCount == 0)
    {
         [self timerExpired];
    } 
    else 
    {
         timeCount--;
        if(timeCount == 0) {
        [timer invalidate];
        [self timerExpired];
    }
 }
   lblTimer.text = [NSString stringWithFormat:@"%02d:%02d",timeCount/60, timeCount % 60];
   self.title = lblTimer.text;
}

将上面的Label Outlet与View中的Label绑定。

它与我一起正常工作

【讨论】:

  • NSRunLoop 如果针对特定 UIView' 控件的操作所调用的事件,将挂起该控件。
  • [自拍过期];抱歉,这是调用什么方法?
【解决方案5】:

您可以使用NSTimer 来实现此目的。

【讨论】:

猜你喜欢
  • 2016-07-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-11-29
  • 2016-08-22
  • 1970-01-01
  • 2011-12-19
相关资源
最近更新 更多