【问题标题】:View controller is not removing Notification Center observer视图控制器没有删除通知中心观察者
【发布时间】:2015-11-10 16:00:29
【问题描述】:

我有这个viewDidLoad 代码:

- (void)viewDidLoad
{
   [super viewDidLoad];

   [[NSNotificationCenter defaultCenter] removeObserver:self];

   [[NSNotificationCenter defaultCenter] addObserver:self
                                            selector:@selector(messageReceived:)
                                             name:@"messageReceived"
                                           object:nil];
}

此视图控制器是UITabBarController 之一。每次我转到它的选项卡时,都会调用viewDidLoad,但似乎[[NSNotificationCenter defaultCenter] removeObserver:self]; 什么都不做,并且每次调用该方法时都会注册“messageReceived”。

此代码 sn-p 来自另一个通知的类:

[[NSNotificationCenter defaultCenter] postNotificationName:@"messageReceived"
                                                            object:nil
                                                          userInfo:nil];

只被调用一次,但是,例如,如果我转到正在观察的视图控制器的选项卡 3 次,并且 viewDidLoad 被调用 3 次,那么它的 messageReceived: 方法也被调用 3 次。 .

我可能会错过什么?

【问题讨论】:

    标签: ios uiviewcontroller uitabbarcontroller observer-pattern nsnotificationcenter


    【解决方案1】:

    您可能想要挂钩以下内容:

    -(void)viewWillAppear:(BOOL)animated
    {
      [super viewWillAppear:animated];
      [[NSNotificationCenter defaultCenter] addObserver:self
                                                selector:@selector(messageReceived:)
                                                 name:@"messageReceived"
                                               object:nil];
    }
    
    -(void)viewWillDisappear:(BOOL)animated
    {
      [super viewWillDisappear:animated];
      [[NSNotificationCenter defaultCenter] removeObserver:self];
    }
    

    当您点击标签栏时,会创建一个新的 UIViewController 实例,因此会调用 viewDidLoad。当您从 viewDidLoad 中调用 removeObserver 方法时,您要求从观察者中删除新创建的视图控制器,此时它从未注册过。

    -viewWillDisappear 在您的视图控制器从视图层次结构中移除之前被调用,因此从该方法调用 removeObserver 应该可以解决问题。

    祝你好运!

    【讨论】:

    • 谢谢。如果我想在应用程序处于后台状态时继续观察会发生什么?是否可以/适合使用通知中心来处理,还是应该使用本地通知?
    • 在这种情况下,您可能希望让您的 AppDelegate 或其他一些持久性控制器而不是您的视图控制器来观察通知。
    • 谢谢。另一个问题由此产生:由于我正在谈论的这个视图控制器总是在用户启动应用程序时加载,并且我已经为位置服务启用了后台模式,只要我继续观察,这个视图控制器就不会持续存在位置更新?
    • 观察任何在后台持续存在的 NSObject(包括 UIViewController),老实说。因此,如果您的视图控制器在后台保持加载状态,那么您是从 AppDelegate 还是从视图控制器观察都无关紧要。
    【解决方案2】:

    我认为您应该在 dealloc 方法中添加“删除观察者”代码,当您的视图将被删除时,arc 会自动调用该代码以进行后台处理,您可以从应用程序委托方法“applicationWillEnterInBackground”和其他方法发布通知..

    【讨论】:

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