24

Okay, I have searched online and even looked in a couple of books for the answer because I can't understand the apple documentation for the NSTimer. I am trying to implement 2 timers on the same view that each have 3 buttons (START - STOP - RESET).

The first timer counts down from 2 minutes and then beeps.

The second timer counts up from 00:00 indefinitely.

I am assuming that all of the code will be written in the methods behind the 3 different buttons but I am completely lost trying to read the apple documentation. Any help would be greatly appreciated.

startuprob
  • 1,917
  • 5
  • 30
  • 45

2 Answers2

35

Basically what you want is an event that fires every 1 second, or possibly at 1/10th second intervals, and you'll update your UI when the timer ticks.

The following will create a timer, and add it to your run loop. Save the timer somewhere so you can kill it when needed.


- (NSTimer*)createTimer {

    // create timer on run loop
    return [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(timerTicked:) userInfo:nil repeats:YES];
}

Now write a handler for the timer tick:

- (void)timerTicked:(NSTimer*)timer {

    // decrement timer 1 … this is your UI, tick down and redraw
    [myStopwatch tickDown];
    [myStopwatch.view setNeedsDisplay]; 

    // increment timer 2 … bump time and redraw in UI
    …
}

If the user hits a button, you can reset the counts, or start or stop the ticking. To end a timer, send an invalidate message:


- (void)actionStop:(id)sender {

    // stop the timer
    [myTimer invalidate];
}

Hope this helps you out.

  • First off, thank you so much for the help but I am still a bit confused. What do I use for the UILabel and the IBAction? Your code doesn't seem to have those which should be in there - shouldn't it? – startuprob Jun 15 '10 at 02:00
  • I *highly* recommend that you pick up a copy of Aaron Hillegass' book, Cocoa(R) Programming for Mac(R) OS X (3rd Edition). If you read this and work through the examples, you will gain a solid understanding of Objective-C and Cocoa, including Interface Builder. Honestly, for $30 and some time, it's probably the best investment you could make. Gotta run, baby to feed! – Jonathan Watmough Jun 15 '10 at 04:21
  • Yes, in answer to your comment, I skipped the implementation of your UI. You're correct, you need a UIWindow, with a UIView containing some controls which will generate events when the users tap them. The events will need to be routed to IBAction tagged methods in your view controller. And as you said, a UILabel or two to hold your stopwatch read-outs. – Jonathan Watmough Jun 15 '10 at 04:36
11

I would follow Jonathan's approach except you should use an NSDate as your reference for updating the UI. Meaning instead of updating the tick based on the NSTimer, when the NSTimer fires, you take the difference between NSDate for now and your reference date.

The reason for this is that the NSTimer has a resolution of 50-100 ms which means your timer can become pretty inaccurate after a few minutes if there's a lot going on to slow down the device. Using NSDate as a reference point will ensure that the only lag between the actual time and the time displayed is in the calculation of that difference and the rendering of the display.

robotpsyche
  • 171
  • 2
  • 6
  • 1
    I know this is old, but incase anyone comes across it: NSTimer actually retains that resolution between fires, meaning it will always be accurate with a resolution of 50-100 ms, never (under anything but extreme cases) worse than that. See Timer Tolerance in the [NSTimer documenation](https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSTimer_Class/). – nickRise Oct 15 '15 at 03:28
  • @robotpsyche is right, I tried using `NSTimer` on two devices (iphone and ipad), guess what, in 20 minutes the difference between the timers was 12 seconds !!!, this is not acceptable at all, I will use `NSDate`. – Amr Lotfy Sep 12 '16 at 17:32