Краткая версия вопроса:
У меня есть класс с кучей объявленных свойств, и я хочу отслеживать, были ли в нем какие-либо изменения, чтобы, когда я вызываю для него метод 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];
}
Это работает отлично, пока вы не установите значение напрямую с помощью установщика (, т.е.myObject.myString = @"new string";
), и в этом случае setValue:forKey:
не называется (Я не уверен, почему я думал, что это будет, лол ).
Попытка 2
Наблюдайте за всеми свойствами себя.
- (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
}
Я почти уверен, что это сработает, но я думаю, что должен быть лучший способ. :)Я также хочу, чтобы это было автоматически, чтобы мне не приходилось вести список свойств для просмотра. Я легко могу заметить, что забываю добавить свойство в список при поддержке этого в будущем, а затем пытаюсь выяснить, почему мой объект иногда не сохраняется.
Надеюсь, я упускаю из виду гораздо более простой подход к этой проблеме!
Окончательное решение
Смотрите мой ответ ниже для моего окончательного решения этого. Он основан на ответе Джоша Касвелла, но является рабочим примером.