Подтвердить что ты не робот

Почему мой 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 сделало трюк. Спасибо за руководство!

4b9b3361

Ответ 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: в качестве отправной точки для регистрации уведомлений