Obj-C, как сохранить / извлечь несколько диапазонов дат и оценить его для использования на основе прошлого или будущего, наименьшего возможного кода? - PullRequest
0 голосов
/ 26 января 2011

Мне нужно быстро создать некоторые функции, которые позволят мне сохранять и извлекать некоторые диапазоны дат. Затем оцените даты на основе текущей даты, а затем добавьте их в массив.

Я не совсем уверен, сколько диапазонов мне нужно сохранить.

Возможно, вы видели подобный пример, который я могу использовать для справки?

EDIT. Мне нужно сохранить их для использования при следующем запуске приложения.

Ответы [ 2 ]

3 голосов
/ 26 января 2011

Вы можете представить диапазон дат двумя способами:

  • дата начала + дата окончания
  • дата начала + продолжительность

Затем вы можете представить дату как экземпляр NSDate, как double (или, если вам крайне необходимо сохранить память, как int, например, метку времени UNIX). Я бы сделал для этого урок.

@interface DateRange : NSObject <NSCoding>
{
    NSTimeInterval start, end;
}
@property (nonatomic, assign) NSDate* startDate;
@property (nonatomic, assign) NSDate* endDate;
@property (nonatomic, assign) NSTimeInterval duration;
- (BOOL) containsDate: (NSDate *) date;
@end

@implementation DateRange

- (NSDate *) startDate
{
    return [NSDate dateWithTimeIntervalSinceReferenceDate: start];
}

- (void) setStartDate: (NSDate *) date
{
    start = [date timeIntervalSinceReferenceDate];
}

- (NSDate *) endDate
{
    return [NSDate dateWithTimeIntervalSinceReferenceDate: end];
}

- (void) setEndDate: (NSDate *) date
{
    end = [date timeIntervalSinceReferenceDate];
}

- (NSTimeInterval) duration
{
    return end - start;
}

- (void) setDuration: (NSTimeInterval) newDuration
{
    end = start + newDuration;
}

- (BOOL) containsDate: (NSDate *) date
{
    NSTimeInterval d = [date timeIntervalSinceReferenceDate];
    return d > start && d < end;
}

- (id) initWithCoder: (NSCoder *) coder
{
    if ( ( self = [super init] ) ) {
        start = [coder decodeDoubleForKey: @"start"];
        end = [coder decodeDoubleForKey: @"end"];
    }
    return self;
}

- (void) encodeWithCoder: (NSCoder *) coder
{
    [coder encodeDouble: start forKey: @"start"];
    [coder encodeDouble: end forKey: @"end"];
}

- (BOOL) isEqual: (id) dateRange
{
    if ( [self class] != [dateRange class] )
        return NO;
    return [self.startDate isEqualToDate: ((DateRange *)dateRange).startDate] && [self.endDate isEqualToDate: ((DateRange *)dateRange).endDate];
}

- (NSInteger) hash
{
    return (NSInteger) (end - start);
}

@end

Бонус в том, что вы можете хранить столько диапазонов в коллекциях Какао (например, NSArray), сколько необходимо. Дорогой читатель, я оставляю тебе лучшее воплощение -isEqual: и -hash в качестве упражнения.

Чтобы сохранить объект DateRange в NSUserDefaults:

NSData *dateRangeArchive = [NSKeyedArchiver archivedDataWithRootObject: dateRange];
[[NSUserDefaults standardUserDefaults] setObject: dateRangeArchive forKey: myKey];

Чтобы прочитать объект DateRange из NSUserDefaults:

DateRange *dr = [NSKeyedUnarchiver unarchiveObjectWithData: [[NSUserDefaults standardUserDefaults] dataForKey: myKey]]; // returns an autoreleased DateRange object

Аналогично, если вам нужно сохранить NSArray of DateRanges, вы можете либо заархивировать весь массив, либо создать массив заархивированных DateRanges (первый должен быть быстрее):

NSData *dateRangeArchive = [NSKeyedArchiver archivedDataWithRootObject: arrayOfDateRanges];
[[NSUserDefaults standardUserDefaults] setObject: dateRangeArchive forKey: myKey];

Если вы считаете, что это слишком много повторяющегося кода для вашего проекта, вы можете расширить NSUserDefaults следующим образом:

@interface NSUserDefaults (MyExtensions)
- (DateRange *) dateRangeForKey: (NSString *) defaultName;
- (void) setDateRange: (DateRange *) dateRange forKey: (NSString *) defaultName;
@end

@implementation NSUserDefaults (MyExtensions)

- (DateRange *) dateRangeForKey: (NSString *) defaultName
{
    return [NSKeyedUnarchiver unarchiveObjectWithData: [self dataForKey: defaultName]];
}

- (void) setDateRange: (DateRange *) dateRange forKey: (NSString *) defaultName
{
    [self setObject: [NSKeyedArchiver archivedDataWithRootObject: dateRange] forKey: defaultName];
}

@end
0 голосов
/ 26 января 2011

Вы можете посмотреть на этот вопрос в качестве примера проверки, находится ли NSDate между двумя другими NSDate. Я бы предложил создать класс «MyDateRange» со свойствами «beginDate» и «endDate» и методом -containsDate:.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...