2012-07-19 71 views
6

我有一个UILabel,我想显示当前时间(HH:mm)(与状态栏中的时间相同)。UILabel当前时间

如何更新标签更改为新时间?如果我安排一个间隔为60秒的NSTimer,那么如果计时器在系统时间的每分钟变化之前触发,则标签可能会长达一分钟的时间?

将计时器的时间间隔设置为1秒会好吗,还是会使用比所需资源更多的资源?还是有另一种方法来确保标签将保持与状态栏时钟同步(最好确切地说,但1秒的lee方式确定)?

回答

5

派遣是你的朋友:

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 
} 

这将降低同步到纳秒,只有当调用的微小变化。我相信这是适合您情况的最佳解决方案。

+0

好吧,修正了代码,现在就像一个魅力! – 2012-07-19 19:34:14

+0

很棒的回答。但是代码可能会导致ARC中的保留周期。我编辑了解决该问题的答案。 – Peng90 2014-07-24 16:18:34

0

我想我会在后台线程中运行一个延迟1秒的NSTimer,让它运行的方法检查当前时间(HH:mm)到标签中显示的当前时间。如果它匹配扔掉,如果它是新的,更新标签。

如果您关注性能,请在第一次返回后,查明距离它下一分钟有多少秒,并让它运行那么长时间的计时器。然后在第一次更新后,定时器以60秒的间隔运行。

0

一秒钟是正确答案。

+0

编程,少即是多。 – Eric 2012-07-19 19:10:47

1

将计时器的时间间隔设置为1秒还是这个 会使用比所需资源更多的资源?

取决于你在做什么。如果您计算pi的第一百万位数,或者渲染数百个3-D对象,则需要每个可以节省的处理器周期。如果CPU在大多数时间空闲,那么您可以使用这些周期来使您的界面看起来不错。

+0

像电池寿命的事情也应该是一个担忧。 – jadengeller 2016-04-22 20:09:25

0

也许你可以设置两个定时器。第一个(被触发一次)用于同步第二个定时器,间隔时间为60s,当系统时间到达HH:00时它会被触发;

1
//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]; 
} 

由于没有“委托”功能来调用以实现此功能,您的计时器将始终“延迟”一段时间。

我会坚持定时器,但派遣理查德罗斯三世提到的也是有效的。

0

不带gettimeofday或块的二精度同步更新。 弱指针和dispatch_async阻止保留周期。

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

获取下一分钟0秒。

@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 

我觉得这是有块保留周期在理查德的回答(它可以固定与__weak + dispatch_async)