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

在一个应用程序中,我使用了几个视图控制器。 在一个视图控制器上,观察者被初始化如下:

[[NSNotificationCenter defaultCenter] removeObserver:self name:@"MyNotification" object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(myMethod:) name:@"MyNotification" object:nil]; 

即使在初始化myMethod:的执行次数之前删除NSNotification myMethod:正由相应视图控制器上重复视图的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没有被调用,但是viewdiddis显示正在调用。

我推ViewController到堆栈的方式如下,其中parent是一个tableview子类(点击这个viewcontroller启动的行:

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

解:

将nsnotification的移除移到viewdiddisappear没有办法。 感谢您的指导!

根据这个描述,一个可能的原因是您的视图控制器被过度保留,而不是当你认为他们是释放。 如果事情过度保留,即使使用ARC,也是很常见的。 所以,你认为你只有一个给定的viewcontroller实例是活动的,而实际上你有几个活的实例,他们都听通知。

如果我在这种情况下,我会在viewcontroller的dealloc方法中放置一个断点,并确保它正确地释放,如果这是您的应用程序的预期devise。

你在哪些方法中注册了观察者?

Applebuild议观察者应该在viewWillAppear:注册viewWillAppear:并且在viewWillDissapear:注销viewWillDissapear:

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

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

  • 应用程序启动一个 – 添加观察者得到调用一次在视图中将出现或视图加载 – 通知被调用一次
  • app进入后台并返回,添加观察者在视图中再次调用将出现或者视图加载。 通知被调用两次。
  • 这个数字会增加你进入后台的次数并回来。
  • 在视图中的代码将消失将不会因为视图仍然在窗口堆栈中,并没有被删除。

解决方法:观察应用程序将在您的视图控制器中活动:

  NSNotificationCenter.defaultCenter().addObserver(self, selector: "applicationWillResign:", name: UIApplicationWillResignActiveNotification, object: nil) func applicationWillResign(notification : NSNotification) { NSNotificationCenter.defaultCenter().removeObserver(self) } 

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

您很可能正在订阅通知

 [[NSNotificationCenter defaultCenter] postNotificationName:@"myNotification" object:self userInfo:userInfo]; 

自我初始化之前。 并试图取消订阅“自我”,这是不是真的订阅,你会得到所有全球myNotification通知。

如果您的视图连接到IB,请使用-awakeFromNib:作为注册通知的起点