Почему мой NSNotification его наблюдатель вызвал несколько раз?
В приложении я использую несколько контроллеров view. На одном наблюдающем контроллере наблюдатель инициализируется следующим образом:
[[NSNotificationCenter defaultCenter] removeObserver:self name:@"MyNotification" object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(myMethod:) name:@"MyNotification" object:nil];
Даже при удалении NSNotification
перед инициализацией количество исполнений myMethod:
суммируется на количество повторных просмотров на соответствующем диспетчере представлений.
Почему это происходит и как я могу избежать myMethod: вызывается более одного раза.
Примечание. Я убедился, используя точки останова, что я не ошибался при вызове postNotification несколько раз.
Изменить: так выглядит моя postNotification
NSArray * objects = [NSArray arrayWithObjects:[NSNumber numberWithInt:number],someText, nil];
NSArray * keys = [NSArray arrayWithObjects:@"Number",@"Text", nil];
NSDictionary * userInfo = [NSDictionary dictionaryWithObjects:objects forKeys:keys];
[[NSNotificationCenter defaultCenter] postNotificationName:@"myNotification" object:self userInfo:userInfo];
edit: даже после перемещения моей подписки на viewwillappear: я получаю тот же результат. myMethod: вызывается несколько раз. (количество раз, когда я перезагружаю viewcontroller).
-(void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[[NSNotificationCenter defaultCenter] removeObserver:self name:@"MyNotification" object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(myMethod:) name:@"MyNotification" object:nil];
}
edit: что-то кажется неправильным в моем жизненном цикле. ViewDidUnload и dealloc не вызываются, однако viewdiddisappear получает вызов.
То, как я нажимаю свой Viewcontroller в стек, выглядит следующим образом, где parent является подклассом tableview (при нажатии на строку, с которой запускается этот диспетчер представлений:
detailScreen * screen = [[detailScreen alloc] initWithContentID:ID andFullContentArray:fullContentIndex andParent:parent];
[self.navigationController pushViewController:screen animated:YES];
Решение:
Перемещение удаления nsnotification в viewdiddisappear сделало трюк. Спасибо за руководство!
Ответы
Ответ 1
Основываясь на этом описании, вероятной причиной является то, что ваши контроллеры просмотра слишком задерживаются и не выпущены, когда вы думаете, что они есть. Это довольно часто встречается даже в ARC, если вещи слишком задерживаются. Итак, вы считаете, что у вас есть только один экземпляр данного элемента управления представлением, в то время как на самом деле у вас есть несколько живых экземпляров, и все они слушают уведомления.
Если бы я был в этой ситуации, я бы поставил точку останова в методе dealloc viewcontrollers и удостоверился, что он освобожден правильно, если это предполагаемый дизайн вашего приложения.
Ответ 2
В каких методах вы зарегистрировали наблюдателей?
Apple рекомендует, чтобы наблюдатели регистрировались в viewWillAppear:
и незарегистрировались в viewWillDissapear:
Вы уверены, что дважды не регистрируете наблюдателя?
Ответ 3
Включите эту проблему в приложении, работающем быстро. Приложение получило уведомление один раз при первом запуске. уведомление увеличивает количество раз, когда вы отправляетесь в фоновый режим и возвращаетесь. то есть
- приложение запускает одно - добавляет, что наблюдатель получает вызывается один раз в представлении, появится или просмотрит загрузку - уведомление вызывается один раз
- приложение переходит в фоновый режим и возвращается, добавляет, что наблюдатель получает вызов снова в представлении, появится или просмотр загрузится. уведомление вызывается дважды.
- число увеличивает количество раз, когда вы переходите на задний план и возвращаетесь.
- код в поле зрения исчезнет, не будет иметь никакого значения, поскольку представление все еще находится в стеке окна и не удалено из него.
решение:
приложение будет отменено в вашем контроллере вида:
NSNotificationCenter.defaultCenter().addObserver(self, selector: "applicationWillResign:", name: UIApplicationWillResignActiveNotification, object: nil)
func applicationWillResign(notification : NSNotification) {
NSNotificationCenter.defaultCenter().removeObserver(self)
}
это позволит убедиться, что ваш контроллер просмотра удалит наблюдателя для уведомления, когда представление переходит в фоновый режим.
Ответ 4
вполне возможно, что вы подписываетесь на уведомления
[[NSNotificationCenter defaultCenter] postNotificationName:@"myNotification" object:self userInfo:userInfo];
до инициализации self. И попытка отказаться от подписки на "я", на которую не подписаны, и вы получите все глобальные уведомления myNotification.
Если ваше представление было подключено в IB, используйте -awakeFromNib: в качестве отправной точки для регистрации уведомлений