2012-10-01 24 views
10

Có thể thêm người quan sát để được thông báo nếu có thuộc tính đối tượng được giám sát nào được sửa đổi không? Ví dụ:KVO cho toàn bộ thuộc tính đối tượng

@interface OtherObject : NSObject 

@property (nonatomic) MyObject* myObject; 

@end 

@interface MyObject : NSObject 

@property (nonatomic) unsigned int property1; 
@property (nonatomic) unsigned int property2; 

@end 

Tôi muốn làm điều gì đó như:

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

và nhận được thông báo nếu một trong hai property1 hoặc property2 được sửa đổi. Nó dường như không hoạt động nếu tôi đăng ký đối tượng đang nắm giữ (bằng cách nào đó có ý nghĩa vì myObject không thực sự được sửa đổi khi tôi sửa đổi property1 chẳng hạn).

Trả lời

12

Tôi có thể nghĩ đến hai tùy chọn.

  • Bạn có thể tạo thuộc tính "chính" riêng và làm cho nó phụ thuộc vào tất cả các thuộc tính khác của bạn.

    @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]; 
    } 
    

    Nếu bạn quan sát masterProperty bạn sẽ được thông báo khi bất kỳ thuộc tính thay đổi.

  • Bạn sử dụng thời gian chạy Objective-C để nhận danh sách tất cả các thuộc tính và quan sát tất cả các thuộc tính.

    - (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

Có lẽ, bạn cũng có thể kết hợp hai phương pháp này, sử dụng thời gian chạy Objective-C để nhận danh sách tất cả các thuộc tính trong keyPathsForValuesAffectingMasterProperty, sau đó trả về chúng trong một NSSet. (Có thể nên sử dụng biến tĩnh để bạn chỉ phải thực hiện một lần.) – dgatwood

2

gì bạn có thể làm là có một chức năng để sửa đổi thuộc tính cụ thể của myObject ...

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

và sau đó trong hàm có mã này ...

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

    myObject.name = name; 

    [self didChangeValueForKey:@"myObject"]; 
} 

chí này sau đó thông báo cho người quan sát khi thuộc tính đó trên myObject bị thay đổi.

Bất cứ ai bạn cần điều này làm sử dụng mẫu này và bạn có thể nhận được thông báo về bất kỳ thay đổi nào trên myObject.

:: EDIT :: Có nói rằng, bạn sẽ có thể sử dụng ...

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

và điều đó sẽ quan sát property1 và làm tương tự pháo đài các thuộc tính khác.

Nhưng điều này có nghĩa là thêm người quan sát cho từng thuộc tính riêng lẻ.

+0

lẽ willChangeValueForKey thay vì willChangeObjectForKey? – Andy

+1

@Andy đã thay đổi. Ngạc nhiên là không được phát hiện trong hai năm. lol! – Fogmeister

Các vấn đề liên quan