21

I am new to iOS programming. I am working on words matching game. In this game I need to implement time counter which shows minutes and seconds. I want when my game is started my timer to start with 3 minutes. Now I want to decrease this timer in reverse direction with seconds. my code just work for seconds..here is my code:

  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];

 }

 }

In Viewdidload i call it through timer..

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

pleas any one guide me how can i do it in both minutes and seconds.

jamil
  • 2,419
  • 3
  • 37
  • 64
  • Please check the following link [Count down timer](http://fromideatoapp.com/downloads/FI2ADemo-Part4.zip) It is also Pretty Handy. Regards, Neil – NIKHIL May 19 '12 at 09:09

6 Answers6

57

You can do it like this(ARC Enabled):-

@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];
    }
}
Abhishek Singh
  • 6,068
  • 1
  • 23
  • 25
  • Thanx Dear @roronoa zorro your Answer is the best solution that i want. – jamil May 19 '12 at 11:06
  • Hi @roronoa-zorro , was wondering how to deal with pausing the timer? – gdubs May 14 '13 at 05:35
  • You cannot pause or restart the Timer , you can only invalidate it.The pause & resume can be replicate by using a NSDate variable , store the current NSDate at the time you want to pause(actually invalidate) & restart the timer from the saved NSDate object – Abhishek Singh May 21 '13 at 14:50
  • 1
    Slightly pedantic comment: `NSTimer` retains its target so this code will cause `ViewController` not to be deallocated unless its timer has reached zero. There are a bunch of workarounds mostly involving proxy objects and weak references and it doesn't even necessary really matter — quite often you have view controllers you know will never be deallocated anyway (such as the root view controller, commonly). – Tommy Sep 05 '13 at 18:19
19

I know this is old question, but I want to share my way to achieve this. We have method (timeIntervalSinceDate:) to calculate the interval and have fixed amount of seconds to count down. In my case 300 s.

UPDATE JULY, 2015 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];
}

UPDATE:

it is extremely expensive to create a NSDateFormatter each time you pass through updateTimer. Far better to create the NSDateFormatter outside the loop and reuse it. Credits: @siburb

Neil Galiaskarov
  • 5,015
  • 2
  • 27
  • 46
  • In case anybody is going to copy/paste this verbatim (you know who you are - ), it is extremely expensive to create a `NSDateFormatter` each time you pass through `updateTimer`. Far better to create the `NSDateFormatter` outside the loop and reuse it. – siburb Dec 14 '16 at 07:39
4

In .h file

 IBOutlet UILabel* lblTimer;
 NSTimer* gameTimer;

In .m file

-(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;
}

Bind the above Label Outlet with Label in View.

It is working correctly with Me

iDhaval
  • 7,824
  • 2
  • 21
  • 30
2

Simple and less code in 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];
}
User558
  • 1,165
  • 1
  • 13
  • 37
1

OBJECTIVE-C

Here what we are going to achieve is a reverse countdown timer with circular progress.

enter image description here

We need to follow some steps to achieve the above result in Objective-C.

A. Create XIB Files.

B. Design the layout

C. Configure the circular progress with this library. MBCircularProgressBarView

D. Populate XIB in the UIViewController.

==============================================================

A. Create XIB Files:

  • Go to Project Navigation and by right click, you will get the options to create a new file -> Cocoa Touch Class -> write Class Name: ProgressDelayView

enter image description here

You will get the .h & .m file named ProgressDelayView

Now we will create a User Interface for the class files.

enter image description here

This time you will get the .xib file named ProgressDelayView

Now, Assign the class name to the Interface file

enter image description here

B. Design the layout

Now design the layout according to your requirement. I have designed based on mine.

C. Configure the circular progress with this library. MBCircularProgressBarView

Assign the attribute properties based on your app theme. please check out the attributes in a screenshot.

enter image description here

D. Populate XIB in the UIViewController.

Let's move to the code part

Open your viewcontroller.h file

and paste this code.

#import <UIKit/UIKit.h>

@interface viewcontroller : UIViewController

@property (nonatomic) int remainingSeconds;

@end

open viewcontroller.m and paste this

#import "viewcontroller.h"
#import "ProgressDelayView.h"

@interface viewcontroller(){
    ProgressDelayView *TimerTicker;
    NSTimer *timer;
}
@implementation viewcontroller
#pragma mark - Controller Lifecycle
- (void)viewDidLoad {
    [super viewDidLoad];
    TimerTicker = [[[NSBundle mainBundle] loadNibNamed:@"ProgressDelayView" owner:self options:nil] objectAtIndex:0];
}

-(void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];
    [self populateTimeTicker];
}

-(void)populateTimeTicker {
    TimerTicker.frame = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height);
    [self showWithAnimation:TimerTicker];
    self.remainingSeconds = 180;
    [self startTicker];
}

-(void)startTicker {
    timer=[NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(timerTicker) userInfo:nil repeats:YES];
}

- (void)timerTicker {
    self.remainingSeconds--;
    if (self.remainingSeconds == -1) {
        //dismiss alertview
        [timer invalidate];
        [TimerTicker removeFromSuperview];
        return;
    }
    [UIView animateWithDuration:1.f animations:^{
        TimerTicker.progress.value = self.remainingSeconds;
    }];
}

-(void)showWithAnimation:(UIView *)customView{
    [UIView animateWithDuration:0.5
                          delay:0.1
                        options: UIViewAnimationOptionCurveEaseIn
                     animations:^{
        customView.frame = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height);
                     }
                     completion:^(BOOL finished){
                     }];
    [self.view addSubview:customView];
}

==============================================================

Check out these two files ProgressDelayView.h & ProgressDelayView.m

ProgressDelayView.h

#import <UIKit/UIKit.h>
#import "MBCircularProgressBarView.h"

NS_ASSUME_NONNULL_BEGIN

@interface ProgressDelayView : UIView
@property (weak, nonatomic) IBOutlet MBCircularProgressBarView *progress;

@end

NS_ASSUME_NONNULL_END

ProgressDelayView.m

#import "ProgressDelayView.h"

@implementation ProgressDelayView

@end

HURRAY hit the ⌘R

Azharhussain Shaikh
  • 1,654
  • 14
  • 17
0

You can use NSTimer to achieve this.

rishi
  • 11,779
  • 4
  • 40
  • 59
  • 1
    Check out this tutorial, it will help you in achieve what you want - http://pravinmagdum.wordpress.com/tag/nstimer-tutorial/ – rishi May 19 '12 at 07:55
  • 1
    Checkout this, might be this is causing issue to you - http://stackoverflow.com/questions/2340930/stray-342-in-c-program – rishi May 19 '12 at 08:27
  • 1
    Thanx now its Work fine Dear @rishi a lot a thanx for helping me.now i satified to accept Your are Answer thanx. – jamil May 19 '12 at 08:40
  • I don't understand your answer and those links. Is it relevant to the question? – Mihir Oza Feb 08 '19 at 12:57