Краткая версия вопроса:
У меня есть класс с тонны объявленных свойств, и я хочу отслеживать, были ли какие-либо изменения в нем, поэтому, когда я вызываю метод save
на нем, он не пишет в базу данных, когда он не нужен. Как обновить свойство isDirty
без написания настраиваемых настроек для всех объявленных свойств?
Более длинная версия вопроса:
Скажем, что у меня есть класс вроде этого:
@interface MyObject : NSObject
{
@property (nonatomic, retain) NSString *myString;
@property (nonatomic, assign) BOOL myBool;
// ... LOTS more properties
@property (nonatomic, assign) BOOL isDirty;
}
...
@implementation MyObject
{
@synthesize myString;
@synthesize myBool;
// ... LOTS more synthesizes :)
@synthesize isDirty;
}
Попытка 1
Моя первая мысль заключалась в том, чтобы реализовать setValue:forKey:
следующим образом:
- (void)setValue:(id)value forKey:(NSString *)key {
if (![key isEqualToString:@"isDirty"]) {
if ([self valueForKey:key] != value) {
if (![[self valueForKey:key] isEqual:value]) {
self.isDirty = YES;
}
}
}
[super setValue:value forKey:key];
}
Это работает отлично, пока вы не установите значение напрямую с помощью setter (т.е. myObject.myString = @"new string";
), и в этом случае setValue:forKey:
не вызывается (я не уверен, почему я думал, что это будет, lol).
Попытка 2
Соблюдайте все свойства self.
- (id)init
{
// Normal init stuff
// Start observing all properties of self
}
- (void)dealloc
{
// Stop observing all properties of self
}
- (void)observeValueForKeyPath:(NSString *)keyPath
ofObject:(id)object
change:(NSDictionary *)change
context:(void *)context
{
// set isDirty to true
}
Я уверен, что это сработает, но я думаю, что должен быть лучший способ.:) Я также хочу, чтобы это было автоматически, так что мне не нужно поддерживать список свойств для просмотра. Я легко вижу, что забываю добавлять свойство в список при сохранении этого вниз по дороге, а затем пытаюсь выяснить, почему мой объект иногда не сохраняется.
Надеюсь, я упустил гораздо более простой подход к этой проблеме!
Окончательное решение
См. Мой ответ ниже для моего окончательного решения. Он основан на ответе, предоставленном Джошем Касуэлом, но является рабочим примером.