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 и делать то же самое, что и другие свойства.

Но это будет означать добавление наблюдателя для каждого свойства по отдельности.