UILabel with current time

I have a UILabel that I want to show the current time (HH: mm) (at the same time as in the status bar).

How to update a shortcut to move to a new time? If I plan to use NSTimer with an interval of 60 seconds, then the label may be out of time for a minute, if the timer is triggered shortly before the time in the system changes?

Can I set the timer interval to 1 second or use more resources than necessary? Or is there another way to make sure that the shortcut will synchronize with the standard clock (preferably accurate, but the first second way is normal)?

+6
source share
7 answers

Dispatch is your friend:

void runBlockEveryMinute(dispatch_block_t block) { block(); // initial block call // get the current time struct timespec startPopTime; gettimeofday((struct timeval *) &startPopTime, NULL); // trim the time startPopTime.tv_sec -= (startPopTime.tv_sec % 60); startPopTime.tv_sec += 60; dispatch_time_t time = dispatch_walltime(&startPopTime, 0); __block dispatch_block_t afterBlock = ^(void) { block(); dispatch_after(dispatch_time(DISPATCH_TIME_NOW, NSEC_PER_SEC * 60), dispatch_get_main_queue(), afterBlock); }; dispatch_after(time, dispatch_get_main_queue(), afterBlock); // start the 'timer' going } 

It will sync until the nanosecond and only ring when the minute changes. I believe that this is the best solution for your situation.

+5
source

Would it be nice to set the timer interval to 1 second, or would it use more resources than necessary?

Depending on what you do. If you are calculating the first millions of digits of pi or rendering several hundred three-dimensional objects, you will need every processor cycle that you can save. If the processor is idling most of the time, you can also use these loops to make your interface look nice.

+1
source
 //Create a timer... timer = [NSTimer scheduledTimerWithTimeInterval:0.25 target:self selector:@selector(tick:) userInfo:NULL repeats:YES]; //Function to update time - (void)tick:(NSTimer*)t { NSDate *now = [NSDate date]; NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init]; [dateFormatter setDateFormat:@"HH:mm:ss"]; NSString *timeString = [dateFormatter stringFromDate:now]; [uilabel setText:timeString]; } 

your timer will always be "delayed" for a while, since there are no "delegate" functions to perform this function.

I would stick with a timer, but the dispatch, as Richard J. Ross III mentioned, is also valid.

+1
source

I think I started NSTimer with a 1 second delay in the background thread, try running the current method (HH: mm) at the current time displayed on the label. If it coincides with its release, if it is new, update the label.

If you are concerned about performance, after you return for the first time, find out how many seconds are left from the next minute and let it start the timer. Then, after updating the first timer, the timer starts at intervals of 60 seconds.

0
source

one second is the correct answer.

0
source

Perhaps you can set two timers. The first (once) is used to synchronize the second timer with an interval of 60 s, which starts it when the system time comes to HH: 00;

0
source

Second-precision synchronized updates without gettimeofday or blocks. A weak pointer and dispatch_async prevent a save loop.

 - (void)updateTimeLabel { if (!timeFormatter) { timeFormatter = [NSDateFormatter new]; timeFormatter.dateStyle = NSDateFormatterNoStyle; timeFormatter.timeStyle = NSDateFormatterShortStyle; } NSDate *currentTime = [NSDate date]; NSTimeInterval delay = [[currentTime nextMinute] timeIntervalSinceDate:currentTime]; timeLabel.text = [timeFormatter stringFromDate:currentTime]; __weak id weakSelf = self; dispatch_async(dispatch_get_main_queue(), ^{ [weakSelf performSelector:@selector(updateTimeLabel) withObject:nil afterDelay:delay]; }); } 

Get the next minute with 0 seconds.

 @implementation NSDate (Utils) - (NSDate *)nextMinute { NSCalendar *calendar = [NSCalendar currentCalendar]; NSDateComponents *comps = [calendar components:(NSCalendarUnit) NSUIntegerMax fromDate:self]; comps.minute += 1; comps.second = 0; return [calendar dateFromComponents:comps]; } @end 

I think there is a save loop with a block in Richard's answer (it can be fixed with __weak + dispatch_async)

0
source

Source: https://habr.com/ru/post/920909/


All Articles