2015-07-29 4 views
5

У меня есть простой ViewController, который KVO податливый и имеет в нем следующее:IOS КВО - Невозможно удалить наблюдатель

- (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"]; 
     } 

вопрос им с в том, что иногда пользователь сообщает следующее сообщение об ошибке:

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

вызов addObserver не вызывается нигде в коде. это что-то о жизненных циклах, которые им не хватает? is not viewDidAppear гарантированно вызывается один раз (так что он должен правильно регистрировать ключи?)

+2

Это не безопасный способ справиться с КВО. Если ваше приложение прервано телефонным звонком, тогда viewWillDisappear не будет вызван, но viewDidAppear может снова вызваться, когда приложение перезагрузится. Есть много других, менее идеальных возможностей. Вы должны рассмотреть возможность использования более надежных методов для добавления и удаления наблюдателей (viewDidLoad, dealloc и т. Д.) – gurooj

+0

спасибо за знания. что произойдет, если я дважды назову addObserver? мне тогда нужно также удалитьObserver? Также в этой статье говорится, что ViewDidAppear вызывается только один раз: http://stackoverflow.com/questions/11534396/when-is-viewdidappear-called – j2emanue

+0

не отвечает на ваш вопрос, но вы можете защитить себя от ошибки с помощью '@try {[self removeObserver : self forKeyPath: @ "yourKeyPath"];} @catch (NSException * __unused exception) {} ' – vib

ответ

4

Нет гарантии, что viewDidAppear будет соответствовать viewWillDisappear каждый раз. Это означает, что ваша регистрация/регистрация KVO потенциально будет несбалансированной и недетерминированной. Вы должны выполнить регистрацию/регистрацию KVO в условиях гарантированной пары, например viewDidLoad и dealloc.

7

Apple Docs сказать, что есть способ добавить наблюдателя, когда вид виден только. Согласно Рисунок 1 - Действительные переходы состояния вы можете использовать пару viewWillAppear/viewWillDisppear для добавления и удаления наблюдателей. В то же время вы можете использовать партию init/dealloc, но не viewDidLoad/dealloc - просмотр может быть не загружен, но контроллер освобожден.

Ваш код должен быть:

- (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"]; 
}