• Open Menu Close Menu
  • Apple
  • Shopping Bag
  • Apple
  • Mac
  • iPad
  • iPhone
  • Watch
  • TV
  • Music
  • Support
  • Search apple.com
  • Shopping Bag

Lists

Open Menu Close Menu
  • Terms and Conditions
  • Lists hosted on this site
  • Email the Postmaster
  • Tips for posting to public mailing lists
Re: Cocoa timer - Using NSTimer or an alternative for timer program
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Cocoa timer - Using NSTimer or an alternative for timer program


  • Subject: Re: Cocoa timer - Using NSTimer or an alternative for timer program
  • From: Alastair Houghton <email@hidden>
  • Date: Wed, 14 Dec 2005 11:25:12 +0000

On 14 Dec 2005, at 04:55, Alphonsus Chong wrote:

Hi,

I'm a newbie to Cocoa trying to write a simple timer program. As a prototype, I used NSTimer to 'tick' at 1 second intervals and that seemed to work fine. However, when I proceeded to get it to fire at 0.01s, it was wildly inaccurate. A search of the Cocoa documentation showed that NSTimer has a resolution of 50-100ms.

I have been cracking my head over this and am pretty sure the answer is pretty simple, but I still can't find it. I would appreciate it if someone could point me to the right direction or suggest a good method to get a timer working with 0.01 second accuracy.

I also read in the same Cocoadev article that runnning NSTimer in a separate thread would give it a better resolution. I wonder if anyone could share their opinion/ experience with that, and whether it would be a good solution.

The thing to realise about timers in event-driven frameworks is that the only guarantee that they generally provide is that they will not fire *before* the next time at which they are supposed to. That being the case, they aren't appropriate for actually timing things; what they *are* useful for, however, is generating a stream of regular events.

Since it isn't entirely apparent what the final application for your timer is, I'll give an example; say I wanted to write a Cocoa app that worked like a digital stopwatch, and was accurate to (say) a thousandth of a second. Clearly there's no point updating the display at that rate (in fact, on Tiger and newer systems, the framework will throttle your display updates if you try to do that), so the right approach is to use an NSTimer with a nominal frequency of (say) 50Hz, and each time it fires, you compute the time difference since the stopwatch started and display that. e.g.

- (IBAction)startStopwatch:(id)sender
{
start = [NSDate timeIntervalSinceReferenceDate];

/* Invalidate just in case someone triggers this method twice with no
intervening stopStopwatch: call. */
[timer invalidate];
timer = [NSTimer scheduledTimerWithTimeInterval:0.02
target:self
selector:@selector(tick)
userInfo:NULL
repeats:YES];
}

- (IBAction)stopStopwatch:(id)sender
{
/* One final tick, to get the final value */
[self tick];

/* No need to release, since it's only retained by the run loop */
[timer invalidate];
timer = nil;
}

- (void)tick:(NSTimer *)theTimer
{
NSTimeInterval now = [NSDate timeIntervalSinceReferenceDate];
NSTimeInterval interval = now - start;
int seconds = (int)interval;
int thousandths = (int)((interval - seconds) * 1000);

[displayedTime setStringValue:
[NSString stringWithFormat:@"d:d:d.d",
(seconds / 3600) % 24,
(seconds / 60) % 60,
seconds % 60,
thousandths]];
}

If you have higher accuracy requirements, then there are some very fast timers, particularly on PowerPC systems where the CPU contains a high-resolution timer that runs at anything up to the full core frequency (depending on the CPU type). Or you might have real-time requirements (perhaps you're doing audio work?) in which case there are probably better solutions (I believe Core Audio already sets things up appropriately, for instance).

One final remark is that if you're doing animation using a timer, then on each timer tick you should measure the actual elapsed time (e.g. using NSDate's -timeIntervalSince... methods) and use that to work out which frame of animation to display (or how far to move things) rather than just displaying one frame for each timer tick; that way, you might skip frames, but the animation will look smooth and the timing will be right.

Kind regards,

Alastair.

p.s. The reason your example doesn't appear to update the text field is that just updating a text field doesn't ordinarily trigger a screen refresh until after the application returns to the event loop... so you'd find that you would only see the last value you set. Plus there's also the display update throttle that I mentioned earlier. Anyway, you don't need to run them on separate threads, you can just do what my example does and return after scheduling an NSTimer to update the display.

--
http://www.alastairs-place.net


_______________________________________________
Do not post admin requests to the list. They will be ignored.
Cocoa-dev mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:

This email sent to email@hidden
References: 
 >Cocoa timer - Using NSTimer or an alternative for timer program (From: Alphonsus Chong <email@hidden>)

  • Prev by Date: Re: Core Data & Drag and Drop, NSTableView SoS
  • Next by Date: Menu bindings & 'Auto Enables Items' ?
  • Previous by thread: Re: Cocoa timer - Using NSTimer or an alternative for timer program
  • Next by thread: -dataWithContentsOfFile returning a NSData object, but no file exists?
  • Index(es):
    • Date
    • Thread