2012-10-01 25 views
10

如果任何受監視的對象屬性被修改,是否可以添加觀察者以獲得通知?例如:整個對象屬性的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在修改property1時沒有真正修改)。

回答

12

我可以考慮兩種選擇。

  • 您可以創建一個單獨的「主」屬性,並使其依賴於所有其他屬性。

    @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); 
    } 
    
+0

假設你也可以結合這兩種方法,使用Objective-C運行時獲得keyPathsForValuesAffectingMasterProperty中所有屬性的列表,然後在NSSet中返回它們。 (使用靜態變量可能是個好主意,所以你只需要做一次。) – dgatwood

2

你可以做的是有一個功能修改myObject的的特定屬性...

-(void)setMyObjectName:(NSString*)name; 

,然後在功能有這樣的代碼......

- (void)setMyObjectName:(NSString*)name 
{ 
    [self willChangeValueForKey:@"myObject"]; 

    myObject.name = name; 

    [self didChangeValueForKey:@"myObject"]; 
} 

這將然後在myObject上的屬性發生更改時通知觀察者。

無論你需要這樣做,使用這種模式,你可以得到通知任何改變myObject。

::編輯:: 說了這麼多,你應該能夠使用...

[otherObject addObserver:self 
       forKeyPath:@"myObject.property1" 
       options:0 
       context:nil]; 

,並且將遵守property1做同樣堡的其他屬性。

但是,這意味着要爲每個屬性單獨添加一個觀察者。

+0

也許willChangeValueForKey willChangeObjectForKey的呢? – Andy

+1

@安迪變了。驚訝的是,雖然兩年沒有發現。大聲笑! – Fogmeister