为什么我的NSNotification会多次调用它的观察者?

时间:2013-11-06 00:11:25

标签: ios iphone uiviewcontroller nsnotificationcenter nsnotifications

在App中我使用了几个viewcontrollers。在一个viewcontroller上,一个观察者初始化如下:

[[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];

编辑:即使在我订阅了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];
}

编辑:我的生命周期似乎出现了问题。 ViewDidUnload和dealloc没有被调用,但是viewdiddisappear被调用。

我将Viewcontroller推送到堆栈的方式如下,其中parent是tableview子类(单击此viewcontroller启动的行:

detailScreen * screen = [[detailScreen alloc] initWithContentID:ID andFullContentArray:fullContentIndex andParent:parent];
[self.navigationController pushViewController:screen animated:YES];

解决方案:

将nsnotification移除到viewdiddisappear就可以了。感谢您的指导!

5 个答案:

答案 0 :(得分:37)

您在哪些方法中注册观察员?

Apple建议观察员应在viewWillAppear:注册并在viewWillDissapear:中取消注册

您确定没有两次注册观察者吗?

答案 1 :(得分:35)

根据此描述,可能的原因是您的viewcontrollers被过度保留,并且在您认为它们时不会被释放。如果事情被过度保留,即使使用ARC,这也很常见。因此,您认为您只有一个给定viewcontroller的实例处于活动状态,而您实际上有几个实时实例,并且它们都会监听通知。

如果我遇到这种情况,我会在viewcontroller的dealloc方法中放置一个断点,并确保它正确解除分配,如果这是你的应用程序的预期设计。

答案 2 :(得分:3)

在运行swift的应用程序中遇到此问题。应用程序首次启动时收到通知。通知会增加您进入后台并返回的次数。即

  • app启动一个 - 添加观察者获取一次在视图中将被调用或视图确实加载 - 通知被调用一次
  • app进入后台并返回,添加观察者在视图中再次调用将出现或查看确实加载。通知被调用两次。
  • 该数字会增加您进入后台并返回的次数。
  • 视图中的代码将消失,因为视图仍在窗口堆栈中并且尚未从中删除。

溶液: 观察应用程序将在视图控制器中激活:

  NSNotificationCenter.defaultCenter().addObserver(self, selector: "applicationWillResign:", name: UIApplicationWillResignActiveNotification, object: nil)

  func applicationWillResign(notification : NSNotification) {
    NSNotificationCenter.defaultCenter().removeObserver(self)
  }

这将确保视图进入后台时视图控制器将删除通知的观察者。

答案 3 :(得分:1)

您很有可能订阅通知

[[NSNotificationCenter defaultCenter] postNotificationName:@"myNotification" object:self userInfo:userInfo];
自我被初始化之前

。并尝试取消订阅并非真正订阅的“自我”,您将获得所有全球 myNotification 通知。

如果您的观点与IB相关联,请使用 -awakeFromNib:作为注册通知的起点

答案 4 :(得分:0)

很可能将带有观察者的类实例化多次。当您进行调试时,该通知有点像多次发布。但是,如果您检查self,则可能会看到每次都是针对不同的实例。

如果您的应用程序使用选项卡栏并且观察者位于您的视图控制器是其子类的基类中,则很容易发生这种情况。