Самый простой способ сделать петлю между двумя NSDates на iPhone? - PullRequest
5 голосов
/ 29 июля 2010

Какой самый простой способ зацикливаться от одной даты к другой?

Концептуально я хочу что-то вроде этого:

for (NSDate *date = [[startDate copy] autorelease]; [date compare: endDate] < 0;
     date = [date dateByAddingDays: 1]) {
    // do stuff here
}

Конечно, это не работает: нетdateByAddingDays:.И даже если бы это было так, это оставило бы широкий след автоматически выпущенных объектов в ожидании их уничтожения.

Вот что я подумал:

  • Я не могу просто добавитьNSTimeInterval, поскольку число секунд в дне может варьироваться.
  • Я могу разбить его на NSDateComponents и добавить один день к компонентам, а затем собрать его.Но это длинный и уродливый код.

Так что я надеюсь, что кто-то попробовал несколько вариантов для этого и нашел хороший.Есть идеи?

Ответы [ 3 ]

7 голосов
/ 29 июля 2010

Установите постоянную компонента даты oneDay и несколько раз добавьте ее:

    NSCalendar *calendar = [NSCalendar currentCalendar];
    NSDateComponents *oneDay = [[NSDateComponents alloc] init];
    [oneDay setDay: 1];

    for (id date = [[startDate copy] autorelease]; [date compare: endDate] <= 0;
        date = [calendar dateByAddingComponents: oneDay
                                         toDate: date
                                        options: 0] ) {
        NSLog( @"%@ in [%@,%@]", date, startDate, endDate );
    }

Это все еще оставляет след автоматически выпущенных объектов, но dateByAddingComponents:toDate:options: несет ответственность. Не уверен, что с этим можно что-то сделать.

4 голосов
/ 26 августа 2011

Как насчет использования date = [date dateByAddingTimeInterval: 24 * 60 * 60] вместо?

for (NSDate *date = [[startDate copy] autorelease]; [date compare: endDate] < 0;
 date = [date dateByAddingTimeInterval:24 * 60 * 60] ) {
    NSLog( @"%@ in [%@,%@]", date, startDate, endDate );
}
3 голосов
/ 29 июля 2010

Добавление быстрого перечисления в класс DateRange:

- (NSUInteger)countByEnumeratingWithState: (NSFastEnumerationState *)state
                                  objects: (id *)stackbuf
                                    count: (NSUInteger)len;
{
    NSInteger days = 0;
    id current = nil;
    id components = nil;
    if (state->state == 0)
    {
        current = [NSCalendar currentCalendar];
        state->mutationsPtr = &state->extra[0];
        components = [current components: NSDayCalendarUnit
                                fromDate: startDate
                                  toDate: endDate
                                 options: 0];
        days = [components day];
        state->extra[0] = days;
        state->extra[1] = (uintptr_t)current;
        state->extra[2] = (uintptr_t)components;
    } else {
        days = state->extra[0];
        current = (NSCalendar *)(state->extra[1]);
        components = (NSDateComponents *)(state->extra[2]);
    }
    NSUInteger count = 0;
    if (state->state <= days) {
        state->itemsPtr = stackbuf;
        while ( (state->state <= days) && (count < len) ) {
            [components setDay: state->state];
            stackbuf[count] = [current dateByAddingComponents: components
                                                       toDate: startDate
                                                      options: 0];
            state->state++;
            count++;
        }
    }
    return count;
}

Это безобразно, но безобразие ограничено моим классом диапазона дат. Мой код клиента просто:

for (id date in dateRange) {
    NSLog( @"%@ in [%@,%@]", date, startDate, endDate );
}

Я думаю, что это, вероятно, достаточно веская причина для создания класса DateRange, если у вас его еще нет.

...