views:

237

answers:

4

I want to display the time (including seconds) in an application in a text field, pretty simple. What I currently do is create a NSTimer that runs every 0.1 seconds that gets the system time and updates the text field. This seems like a terribly inefficient way to accomplish this. Is there a better way?

+4  A: 

Are you displaying it to tenth-of-a-second (or finer) resolution?

If so, I see no problem. Usually, polling sucks because what you're checking might not have changed, but it's not like time is going to stop on you. So a tenth-of-a-second timer is fine.

If not, create a timer whose interval is the desired resolution, then get its fire date, round it down to the desired resolution (e.g., a whole second if you update every second), and set that as the new fire date. Then, your timer will only fire coincidentally with the times it's appropriate to update your clock view.

Note that while time always moves, it doesn't always move linearly: it may jump ahead or backward by an hour or half an hour, or any amount if the user (or ntpd) changes the system clock setting. On Mac OS X 10.6 and later, you can observe for the NSSystemClockDidChangeNotification, and re-adjust your timer's fire date when that happens.

Peter Hosey
I'm only displaying at one second resolution. But if I poll at a second I could be, for example, .9 seconds late on the my text update. If a user has the "display seconds" option set on their clock on the menu bar, I want the app to appear to update the time text at the exact time the menu bar changes seconds, thus polling 10 times a second.
rscott
You won't be 0.9 seconds late if you've set the fire date properly. The timer would have to lag pretty hard to pull that off—and if it's lagged by 0.9 seconds, setting its interval to 0.1 seconds isn't going to help.
Peter Hosey
A: 

I'm not sure what else would be more efficient. As long as the callback for your timer is not doing anything too intensive, you're probably close to optimal.

Shaggy Frog
A: 

How about using gettimeofday(2)? It returns much exact time information to use.

KatokichiSoft
That doesn't keep the display updated, though. Getting the current time is not the hard part; it's the periodic updating that the questioner was wondering about. Also, your claim that `gettimeofday` “returns much [more] exact time information” lacks a comparison: More exact than what?
Peter Hosey
+1  A: 

How about you use NSTimer that runs every second and then you check the firing time and make sure it is exactly on the start of a second. You can use initWithFireDate:interval:target:selector:userInfo:repeats: or set the next invocation time appropriately using setFireDate: after the timer was created:

NSTimeInterval interval = [[timer fireDate] timeIntervalSinceReferenceDate];
NSTimeInterval nextFire = ceil(interval);
[timer setFireDate: [NSDate dateWithTimeIntervalSinceReferenceDate: nextFire];

Then you'll be sure that the timer fires as close to the needed time as possible and don't worry about the timer lagging behind because it resets itself after each firing using intended firing date and interval you provided, so it will always try to fire at exact second (but will fire whenever the run loop will be able to do that).

inkredibl