28

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

[[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: 被多次调用。(我重新加载视图控制器的次数)。

-(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 就可以了。谢谢指导!

4

5 回答 5

40

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

如果我在这种情况下,我会在视图控制器的 dealloc 方法中放置一个断点,并确保它被正确地释放,如果这是你的应用程序的预期设计。

于 2013-11-06T00:58:13.997 回答
39

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

Apple 建议观察者应viewWillAppear:viewWillDissapear:

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

于 2013-11-06T00:25:56.127 回答
5

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

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

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

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

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

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

于 2015-02-03T01:26:51.907 回答
1

您很可能正在订阅通知

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

self被初始化之前。并尝试取消订阅未真正订阅的“自我”,您将获得所有全局myNotification通知。

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

于 2013-11-06T00:43:56.810 回答
0

带有观察者的类很可能被多次实例化。当您调试时,它看起来像是多次发布通知。但是,如果您检查self一下,您可能会发现每次都是针对不同的实例。

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

于 2019-11-08T19:04:56.653 回答