2015-07-29 29 views
5

Tôi có một ViewController đơn giản đó là KVO tuân thủ và có những điều sau đây trong nó:iOS KVO - Không thể loại bỏ một người quan sát

- (void) viewDidAppear:(BOOL)animated 
    { 
     [super viewDidAppear:animated]; 



     [self addObserver:self forKeyPath:@"importStuff" options:0 context:NULL]; 
     [self addObserver:self forKeyPath:@"importStuffFailed" options:0 context:NULL]; 
     } 

    - (void) viewWillDisappear:(BOOL)animated 
    { 
     [super viewWillDisappear:animated]; 

     [self removeObserver:self forKeyPath:@"importStuff"]; 
     [self removeObserver:self forKeyPath:@"importStuffFailed"]; 
     } 

sự im vấn đề gặp là đôi khi người dùng được thông báo lỗi sau:

Cannot remove an observer <MyViewController 0x145d0c8d0> for the key path "importStuff" from <MyViewController 0x1741b2280> because it is not registered as an observer. 

cuộc gọi addObserver không được gọi bất kỳ nơi nào khác trong mã. nó có phải là một cái gì đó về vòng đời im mất tích? không phải viewDidAppear được bảo đảm để được gọi một lần (vì vậy nó phải đăng ký các khóa phải không?)

+2

Đây không phải là một cách an toàn để xử lý KVO. Nếu ứng dụng của bạn bị gián đoạn bởi một cuộc gọi điện thoại, thì viewWillDisappear sẽ không được gọi, nhưng viewDidAppear có thể được gọi lại khi ứng dụng khởi chạy lại. Có rất nhiều khả năng lý tưởng khác. Bạn nên xem xét sử dụng các phương pháp đáng tin cậy hơn để thêm và xóa các quan sát viên (viewDidLoad, dealloc, v.v.) – gurooj

+0

cảm ơn vì kiến ​​thức. điều gì xảy ra nếu tôi gọi addObserver hai lần? tôi có phải removeObserver hai lần không? Ngoài ra bài viết này nói ViewDidAppear chỉ được gọi một lần: http://stackoverflow.com/questions/11534396/when-is-viewdidappear-called – j2emanue

+0

không trả lời câu hỏi của bạn nhưng bạn có thể tự bảo vệ mình khỏi lỗi với '@try {[self removeObserver : self forKeyPath: @ "yourKeyPath"];} @catch (NSException * __unused exception) {} ' – vib

Trả lời

4

Không đảm bảo rằng viewDidAppear sẽ được kết hợp với mỗi lần viewWillDisappear. Điều này có nghĩa là đăng ký/hủy đăng ký KVO của bạn sẽ có khả năng không cân bằng và không xác định. Bạn nên thực hiện đăng ký KVO/hủy đăng ký trong các cặp được đảm bảo như viewDidLoaddealloc.

7

Apple Docs nói rằng có cách thêm người quan sát khi chế độ xem chỉ hiển thị. Theo số Hình 1 - Chuyển tiếp trạng thái hợp lệ, bạn có thể sử dụng cặp viewWillAppear/viewWillDisppear để thêm và xóa người quan sát. Đồng thời, bạn có thể sử dụng cặp init/dealloc nhưng không được viewDidLoad/dealloc - chế độ xem có thể không được tải, nhưng bộ điều khiển đã được deallocated.

Mã của bạn nên là:

- (void)viewWillAppear:(BOOL)animated 
{ 
    [super viewWillAppear:animated]; 

    [self addObserver:self forKeyPath:@"importStuff" options:0 context:NULL]; 
    [self addObserver:self forKeyPath:@"importStuffFailed" options:0 context:NULL]; 
} 

- (void)viewWillDisappear:(BOOL)animated 
{ 
    [super viewWillDisappear:animated]; 

    [self removeObserver:self forKeyPath:@"importStuff"]; 
    [self removeObserver:self forKeyPath:@"importStuffFailed"]; 
} 
Các vấn đề liên quan