【问题标题】:Why is my NSNotification its observer called multiple times?为什么我的 NSNotification 它的观察者被多次调用?
【发布时间】:2013-11-06 00:11:25
【问题描述】:

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

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

即使在初始化 myMethod: 的执行次数之前删除 NSNotification 时,也会被相应视图控制器上重复视图的数量相加。

为什么会发生这种情况以及如何避免 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 就可以了。感谢指导!

【问题讨论】:

  • 你的解决方案对我有用thanq....
  • @BarryK88 thnx 解决方案:帮助
  • 我以某种方式完成的另一件会导致类似问题的事情被声明为NSString * const ABCSomeNotification 两次...

标签: ios iphone uiviewcontroller nsnotificationcenter nsnotifications


【解决方案1】:

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

如果我遇到这种情况,我会在 viewcontroller 的 dealloc 方法中设置一个断点,并确保它被正确释放,如果这是您应用的预期设计的话。

【讨论】:

  • 确实我的 viewDidUnload 和 dealloc 方法没有被调用。我仍然知道为什么。 (编辑我的问题)
  • 如果您不这样做,您还应该在视图控制器的 dealloc 方法中删除Observer:self。否则,NSNotificationCenter 将保留视图控制器,并且永远不会被释放。
  • 顺便说一句,viewDidUnload 仅适用于 5,请不要指望它会触发。
  • 我不知道是否删除了引用,但在后退按钮中我正在执行 self.navigationController.popToRootViewController(animated : true)。我的观察员多次打电话。你能解释一下吗?
【解决方案2】:

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

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

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

【讨论】:

  • 我在 initWith: 启动方法中初始化它
  • @BarryK88 我不会将它添加到启动方法中。 2 个原因:1) self 可能没有正确形成,2) 它可能永远不会出现在屏幕上,在这种情况下你可能不想添加通知。
【解决方案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 被初始化之前。并尝试取消订阅未真正订阅的“self”,您将收到所有全局 myNotification 通知。

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

    【讨论】:

      【解决方案5】:

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-05-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多