2011-01-17 2 views
4

Каков наилучший способ реагирования на изменения данных при вызове свойств. Например, если у меня есть свойство, называемое data, как я могу реагировать, когда вызывается [object setData:newData] и все еще использует синтезированный сеттер. Инстинктивно, я бы переопределить синтезированный сеттер так:Реагирование на сеттеры

- (void)setData:(DataObject *)newData { 
    // defer to synthesised setter 
    [super setData:newData]; 

    // react to new data 
    ... 
} 

... но, конечно, это не имеет смысла - я не могу использовать super как это. Итак, каков наилучший способ справиться с этой ситуацией? Должен ли я использовать KVO? Или что-то другое?

ответ

4

Существует несколько различных способов сделать это, в зависимости от того, какой контроль вы хотите. Один из способов сделать это, чтобы наблюдать собственное свойство:

[self addObserver:self forKeyPath:@"data" options:0 context:nil]; 

- (void)observeValueForKeyPath:(NSString *)path ofObject:(id)object change:(NSDictionary *)change context:(void *)context { 
    if(object == self && [path isEqualToString:@"data"]) { 
     //handle change here 
    } else [super observeValueForKeyPath:path ofObject:object change:change context:context]; 
} 

Убедитесь, что вы удалите себя в качестве наблюдателя в вашем dealloc или завершить метод, если не раньше.

Другим способом было бы переопределить -didChangeValueForKey:. Однако этот метод не может быть вызван, если на объекте нет наблюдателей.

- (void)didChangeValueForKey:(NSString *)key { 
    [super didChangeValueForKey:key]; 
    if([key isEqualToString:@"data"]) { 
     //handle change here 
    } 
} 
+0

Да, KVO - это путь. – JeremyP

+1

Переопределение '-didChangeValueForKey:' не рекомендуется. Если вы используете автоматические уведомления KVO (что делает большинство классов), этот метод не будет вызываться до тех пор, пока наблюдатель не будет добавлен. –

+0

@Mike: Вот почему его единственный второй вариант. – ughoavgfhw

2

@synthesize создает устройства доступа по умолчанию для удобства использования. Если требуется какое-то специальное действие, всегда можно писать собственные аксессоры вместо использования @synthesize. Установщик и получатель не наследуются от базового класса, они создаются директивой @synthesize. Поэтому вам не нужно (ни вы не можете) называть super setData: (если вы действительно не создали суперкласс, который поддерживает это).

Просто убедитесь, что вы правильно управляете памятью. Memory Management Programming Guide содержит примеры того, как управлять памятью для разных типов политики памяти (сохранить или назначить или скопировать).

+0

Я пытаюсь выяснить, есть ли способ, которым я могу иметь это в обоих направлениях: реагировать на изменение _and_ сохранить реализацию, предоставленную '@ synhesize'. Неправильное переопределение аксессуаров и добавление управления памятью. Может быть, более чистый способ реагировать на изменения собственности? –

+0

Это на самом деле не так, но не то, что не рекомендуется. Лично я предпочитаю это. Очевидно, что могут быть и другие способы. посмотрим, что предлагают другие люди. – taskinoor

+0

Для KVO, пожалуйста, проверьте http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/KeyValueObserving/Concepts/AutoVsManual.html. В нем говорится: «Вы можете контролировать автоматические уведомления наблюдателя для свойств вашего подкласса, внедряя метод класса автоматическиNotifiesObserversForKey :.», хотя я сам этого не тестировал. Так что не могу сказать, как сложно это реализовать. – taskinoor

0

От this SO answer.

Вы можете определить «частной» собственности синтезированный, (это в вашем файле .m)

@interface ClassName() 

// Declared properties in order to use compiler-generated getters and setters 
@property (nonatomic, strong <or whatever>) NSObject *privateSomeObject; 

@end 

, а затем вручную определить геттер и сеттер в «публичной» части ClassName (.h и @implementation части), как это,

- (void) setSomeObject:(NSObject *)someObject { 
    self.privateSomeObject = someObject; 
    // ... Additional custom code ... 
} 

- (NSArray *) someObject { 
    return self.privateSomeObject; 
} 

Теперь Вы можете получить доступ к «собственности» someObject как обычно, например, object.someObject. Вы также получаете преимущество автоматически созданного retain/release/copy, совместимого с ARC и почти не теряющего потокобезопасности.

Смежные вопросы