Вы можете представить диапазон дат двумя способами:
- дата начала + дата окончания
- дата начала + продолжительность
Затем вы можете представить дату как экземпляр 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