Objective-C Выполнять метод в данное время ежедневно - грязная реализация - PullRequest
0 голосов
/ 28 января 2012

У меня есть следующий (terible) метод, который постоянно проверяет текущее время, и когда достигается определенное время (в данном случае полночь), оператор NSLog запускается один раз, чтобы показать, что что-то полезное делается:

- (void) checkTime {

while (true){

    NSAutoreleasePool *loopPool = [[NSAutoreleasePool alloc] init];

    NSDate *now = [[NSDate alloc] init];

    NSDateFormatter *outputFormatter = [[NSDateFormatter alloc] init];
    [outputFormatter setDateFormat:@"HH:mm"];

    NSString *nowDateString = [outputFormatter stringFromDate:now];

    if([nowDateString isEqualToString:@"00:00"]){
        NSLog(@"Store previous days data..");
        BOOL stillMidnight = YES;
        while(stillMidnight == YES){
            NSDate *latestNow = [[NSDate alloc] init];

            NSDateFormatter *latestOutputFormatter = [[NSDateFormatter alloc] init];
            [latestOutputFormatter setDateFormat:@"HH:mm"];

            NSString *latestString = [latestOutputFormatter stringFromDate:latestNow];
            //Check if it is still midnight
            if([latestString isEqualToString:@"00:01"]){
                //leave while
                stillMidnight = NO;
            }
        }
        NSLog(@"No longer midnight");
    }

    [loopPool drain];

}

}

Вышеупомянутый метод вызывается следующим образом из метода applicationDidFinishLaunchingWithOption:

[self performSelectorInBackground:@selector(checkTime) withObject:nil];

Этот код запускает NSLog (@ "Хранить данные предыдущих дней ..") один раз в полночьЧто мне нужно, но есть ли более элегантное решение этой проблемы?

Спасибо,

Джек

Ответы [ 3 ]

5 голосов
/ 28 января 2012

Вам было бы лучше:

  1. получение текущей даты;
  2. работает, когда сегодня полночь;
  3. планирование таймера однократного срабатывания через день после этого; и
  4. повторение

Соблазнительно просто запланировать повторяющийся таймер, который сначала срабатывает с датой, рассчитанной в (3), и, следовательно, каждые 24 часа, но это не позволит обеспечить переход на летнее время. Так, например, (закодировано прямо здесь, не проверено)

- (void)scheduleNextTimedAction
{
    // get the date now and the calendar the user is using
    // (which will include their time zone, helpfully)
    NSDate *dateNow = [NSDate date];
    NSCalendar *relevantCalendar = [NSCalendar currentCalendar];

    // decompose the current date to components; we'll
    // just ask for month, day and year here for brevity;
    // check out the other calendar units to decide whether
    // that's something you consider acceptable
    NSDateComponents *componentsForNow =
         [relevantCalendar components:
                  NSYearCalendarUnit|NSMonthCalendarUnit|NSDayCalendarUnit
                  fromDate:dateNow];

    // we could explicitly set the time to midnight now,
    // but since that's 00:00 it'll already be the value
    // in the date components per the standard Cocoa object
    // creation components, so...

    // get the midnight that last occurred
    NSDate *lastMidnight = [relevantCalendar dateFromComponents:componentsForNow];

    // can we just add 24 hours to that? No, because of DST. So...

    // create components that specify '1 day', however long that may be
    NSDateComponents *oneDay = [[NSDateComponents alloc] init];
    oneDay.day = 1;

    // hence ask the calendar what the next midnight will be
    NSDate *nextMidnight = [relevantCalendar
                 dateByAddingComponents:oneDay
                 toDate:lastMidnight
                 options:0];
    [oneDay release];

    // now create a timer to fire at the next midnight, to call
    // our periodic function. NB: there's no convenience factory
    // method that takes an NSDate, so we'll have to alloc/init
    NSTimer *timer = [[NSTimer alloc]
                 initWithFireDate:nextMidnight
                 interval:0.0 // we're not going to repeat, so...
                 target:self
                 selector:@selector(doTimedAction:)
                 userInfo:nil
                 repeats:NO];

    // schedule the timer on the current run loop
    [[NSRunLoop currentRunLoop]
                 addTimer:timer
                 forMode: NSDefaultRunLoopMode];

    // timer is retained by the run loop, so we can forget about it
    [timer release];
}

- (void)doTimedAction:(NSTimer *)timer
{
    NSLog(@"do action");
    [self scheduleNextTimedAction];
}
3 голосов
/ 28 января 2012

Если вы хотите выполнить код в произвольный момент времени, лучше всего настроить локальные уведомления.

0 голосов
/ 28 января 2012

Вы можете использовать либо UILocalNotification, если таймер также должен предупреждать пользователя, когда ваше приложение не работает Руководство по push-уведомлениям или NSTimer , которое можно инициализировать с датой запуска или интервал, а также селектор для вызова. Обратите внимание, что NSTimer не будет срабатывать, если ваше приложение находится в фоновом режиме, но в этом случае оно будет срабатывать, как только ваше приложение снова станет активным.

...