KVO для всех свойств объекта
Можно ли добавить наблюдателя для получения уведомления, если изменено какое-либо из свойств контролируемого объекта? Например:
@interface OtherObject : NSObject
@property (nonatomic) MyObject* myObject;
@end
и
@interface MyObject : NSObject
@property (nonatomic) unsigned int property1;
@property (nonatomic) unsigned int property2;
@end
Я хотел бы сделать что-то вроде:
[otherObject addObserver:self
forKeyPath:@"myObject"
options:0
context:nil]
и получать уведомление, если изменяется свойство property1 или property2. Кажется, что это не работает, если я регистрирую объект-держатель (как-то имеет смысл, потому что myObject не изменяется, когда я изменяю свойство1, например).
Ответы
Ответ 1
Я могу представить два варианта.
-
Вы можете создать отдельное свойство "master" и сделать его зависеть от всех ваших других свойств.
@interface MyObject : NSObject
@property (nonatomic) id masterProperty;
@property (nonatomic) unsigned int property1;
@property (nonatomic) unsigned int property2;
@end
+ (NSSet *)keyPathsForValuesAffectingMasterProperty {
return [NSSet setWithObjects:@"property1", @"property2", nil];
}
Если вы наблюдаете masterProperty
, вы будете уведомлены, когда какое-либо из свойств изменится.
-
Вы используете среду выполнения Objective-C, чтобы получить список всех свойств и наблюдать за ними.
- (void)addObserverForAllProperties:(NSObject *)observer
options:(NSKeyValueObservingOptions)options
context:(void *)context {
unsigned int count;
objc_property_t *properties = class_copyPropertyList([self class], &count);
for (size_t i = 0; i < count; ++i) {
NSString *key = [NSString stringWithCString:property_getName(properties[i])];
[self addObserver:observer forKeyPath:key
options:options context:context];
}
free(properties);
}
Ответ 2
Что вы можете сделать, так это иметь функцию для изменения определенного свойства myObject...
-(void)setMyObjectName:(NSString*)name;
а затем в функции есть этот код...
- (void)setMyObjectName:(NSString*)name
{
[self willChangeValueForKey:@"myObject"];
myObject.name = name;
[self didChangeValueForKey:@"myObject"];
}
Затем будет уведомляться наблюдатель, когда это свойство в myObject будет изменено.
Вам нужно, чтобы это использовало этот шаблон, и вы можете получать уведомления о любых изменениях в myObject.
:: EDIT::
Сказав это, вы сможете использовать...
[otherObject addObserver:self
forKeyPath:@"myObject.property1"
options:0
context:nil];
и это будет наблюдать свойство1 и делать то же самое, что и другие свойства.
Но это будет означать добавление наблюдателя для каждого свойства по отдельности.