2010-11-10 37 views
14

Tôi có hai lớp trong lớp ứng dụng A và Lớp B. Cả lớp A và B là các bản sao của UIViewController. Lớp A có một nút khi đẩy đẩy lớp B lên ngăn xếp. Lớp B có một chuỗi mà lớp A muốn quan sát và cập nhật giao diện của nó khi cần thiết. Tôi đã có thể sử dụng: [self addObserver:self forKeyPath:@"name" options:0 context:NULL]; trong lớp B để xem các thay đổi đối với chuỗi. Khi tôi cố gắng và sử dụng sau đây trong lớp A viewWillAppear phương pháp:KVO trên iPhone giữa hai lớp

ClassB *b = [[ClassB alloc]init]; 
[b addObserver:self forKeyPath:@"name" options:0 context:NULL]; 

và thêm phương pháp:

(void)observeValueForKeyPath:(NSString)keyPath ofObject:(id)object 
         change:(NSDictionary)change 
        context:(void)context 

Không có hành động được kích hoạt khi cố gắng để xem các bản cập nhật được thực hiện tại B từ A. Tôi cảm thấy ngớ ngẩn khi hỏi câu hỏi này nhưng KVO hoạt động như thế nào giữa hai lớp trong iOS? Tôi biết điều này sẽ làm việc.

Trả lời

38

Bạn có thể quan sát các thay đổi trên các đối tượng/lớp khác nhau. Tôi nghĩ rằng vấn đề nằm trong tham số tùy chọn của addObserver:forKeyPath:options:context:.

Có nhiều tùy chọn khác nhau cho loại quan sát bạn muốn thực hiện. KVO Guide là một điểm khởi đầu tốt, nhưng bạn có thể muốn NSKeyValueObservingOptionNew, mà tôi sử dụng trong ví dụ bên dưới.

Trước tiên, "tên" phải là tài sản công khai trong ClassB.

Thứ hai, có thể bạn không cần phải thêm người quan sát vào "b" trong viewWillAppear trong ClassA, vì bạn không cần phải thêm nó mỗi khi chế độ xem ClassA sẽ xuất hiện. Bạn chỉ cần thêm người quan sát một lần, khi bạn tạo chế độ xem ClassB. Khi bạn đã thêm người quan sát, phương thức observeValueForKeyPath:ofObject:change:context: sẽ được thực thi trong ClassA, vì vậy bạn có thể cập nhật giao diện người dùng ClassA từ đó. Bạn không nên làm bất cứ điều gì mỗi khi ClassA sắp xuất hiện.

Trong lớp A, bạn có thể tạo ClassB ngay trước khi bạn đẩy ClassB lên ngăn điều khiển, có lẽ trong trình xử lý sự kiện đối với một số hành động mà người dùng đã thực hiện. Ngay sau khi bạn tạo ClassB, hãy thêm người quan sát vào ClassA với giá trị NSKeyValueObservingOption chính xác.

Nếu bạn chỉ muốn được thông báo bất cứ khi nào tài sản công cộng "name" trong ClassB được thay đổi, sau đó thử này:

ClassB

ClassA

@interface ClassA : UIViewController { 
} 

@property (nonatomic, retain) IBOutlet UILabel* nameLabel; 

- (IBAction) someEventHandler:(id)sender; 

@end 

@implementation ClassA 

- (IBAction) someEventHandler:(id)sender { 
    ClassB* b = [[ClassB alloc]init]; 
    [b addObserver:self forKeyPath:@"name" options:NSKeyValueObservingOptionNew context:NULL]; 
    [self.navigationController pushViewController:b animated:YES]; 
    [b release]; 
} 

- (void) observeValueForKeyPath:(NSString*)keyPath ofObject:(id)object change:(NSDictionary*)change context:(void*)context { 
    if ([keyPath isEqual:@"name"]) { 
     NSString* changedName = [change objectForKey:NSKeyValueChangeNewKey]; 
     // do something with the changedName - call a method or update the UI here 
     self.nameLabel.text = changedName; 
    } 
} 

@end 
+0

Đây có lẽ là vấn đề. Bạn cần sử dụng tham số tùy chọn để cho biết bạn muốn thông báo nào. Bằng cách đi qua 0, bạn không yêu cầu được thông báo về bất cứ điều gì. – benzado

+0

nekno, Cảm ơn sự giúp đỡ! – fmcauley

+6

Nếu điều này giúp bất kỳ ai, tôi đã gặp sự cố khi thông điệp ObservValueForKeyPath của tôi không kích hoạt, mặc dù tôi đã viết nó gần giống y như nekno. Bạn * CÓ * để thay đổi thuộc tính bằng self.name = newvalue, * NOT * chỉ name = newvalue. – Mirkules

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