6

現在の時刻(HH:mm)(ステータスバーと同じ時刻)を表示したいUILabelがあります。

ラベルを更新して新しい時刻に変更するにはどうすればよいですか?NSTimerを60秒間隔でスケジュールした場合、システム時刻の分が変わる直前にタイマーが起動すると、ラベルが最大1分遅れる可能性がありますか?

タイマーの間隔を1秒に設定しても問題ありませんか、それとも必要以上のリソースを使用しますか?または、ラベルがステータスバーの時計と同期していることを確認する別の方法はありますか(できれば正確ですが、1秒のリーウェイで問題ありません)。

4

7 に答える 7

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
}

これはナノ秒まで同期し、分が変更されたときにのみ呼び出します。これがあなたの状況に最適な解決策だと思います。

于 2012-07-19T19:03:21.547 に答える
1

タイマーの間隔を1秒に設定しても問題ありませんか、それとも必要以上のリソースを使用しますか?

あなたがしていることに依存します。円周率の最初の100万桁を計算する場合、または数百の3Dオブジェクトをレンダリングする場合は、余裕のあるすべてのプロセッササイクルが必要になります。CPUがほとんどの時間アイドリングしている場合は、これらのサイクルを使用してインターフェイスの見栄えを良くすることもできます。

于 2012-07-19T18:56:43.043 に答える
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];
}

そのような機能を作成するために呼び出す「委任」関数がないため、タイマーは常にしばらくの間「遅延」します。

私はタイマーに固執しますが、リチャードJ.ロスIIIが述べたように派遣も有効です。

于 2012-07-19T19:41:58.880 に答える
0

バックグラウンドスレッドで1秒の遅延でNSTimerを実行し、実行するメソッドに現在の時刻(HH:mm)をラベルに表示されている現在の時刻までチェックさせると思います。一致する場合は破棄し、新しい場合はラベルを更新します。

パフォーマンスが気になる場合は、最初に戻った後、次の分から何秒離れているかを調べて、タイマーをその時間実行させます。次に、最初の更新後、タイマーを60秒間隔で実行します。

于 2012-07-19T18:55:38.650 に答える
0

1秒が正解です。

于 2012-07-19T18:55:46.273 に答える
0

多分あなたは2つのタイマーを設定することができます。最初のタイマー(1回起動)は、2番目のタイマーを60秒間隔で同期するために使用されます。これにより、システム時刻がHH:00になると起動されます。

于 2012-07-19T19:05:57.593 に答える
0

gettimeofdayまたはブロックなしの2次精度の同期更新。ポインタを弱くし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で修正される可能性があります)

于 2014-01-29T14:57:39.420 に答える