【问题标题】:NSNotificationCenter with respect to ViewWillAppear and ViewWillDisapperNSNotificationCenter 关于 ViewWillAppear 和 ViewWillDisapper
【发布时间】:2013-03-30 18:15:17
【问题描述】:

我有一个简单的 viewController,我想监听 UIKeyboardWillHideNotification。因此我有以下代码:

- (void) viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(keyboardWillBeHidden)
                                                 name:UIKeyboardWillHideNotification object:nil];
}

- (void) keyboardWillBeHidden
{
    [self.scrollView setContentOffset:CGPointMake(0, 0) animated:YES];
}

我正在尝试决定何时将 viewController 作为通知中心观察者移除。当视图控制器在屏幕上时,我只需要知道UIKeyboardWillHideNotification,因此我正在考虑添加以下内容:

- (void) viewWillDisappear:(BOOL)animated
{
    [super viewWillDisappear:animated];
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

这就足够了吗?是否有可能在 viewController 仍在屏幕上时调用 viewDidUnloaddealloc 请注意,我正在使用非常基本的 UINavigationController 来处理我的应用程序流。

【问题讨论】:

  • 为什么不删除dealloc中的Observer?
  • 我可以,但这似乎有点过分,因为当视图控制器不在屏幕上时我不需要知道通知。

标签: iphone ios objective-c nsnotificationcenter viewwillappear


【解决方案1】:

viewWillAppear 中注册通知并在viewWillDisappear 中取消注册对我来说似乎是一个干净且对称的解决方案。

请注意,viewWillAppear 可以在 dealloc 之前多次调用(例如,如果另一个视图控制器被推送到您的 VC 上,或者如果您在标签栏控制器之间切换。)如果您在 viewWillAppear 中注册通知并取消注册它仅在 dealloc 中,然后您将获得重复注册(比较 Warning for iOS/iPhone users about duplicate NSNotification observations),并且已注册的选择器被多次调用以用于单个通知事件。

我其实更喜欢基于块的观察者注册方法

addObserverForName:object:queue:usingBlock:

返回一个不透明的对象,用于再次移除观察者。将此返回值存储到视图控制器的实例变量中有助于跟踪观察者是否已注册,因此有助于避免重复注册。

【讨论】:

  • 那么当你使用addObserverForName方法的时候,我还会把它放在viewWillAppearviewWillDisapper中吗?
  • @Nosrettap:是的。所以在这种情况下它并没有太大的区别,我只是提到了这个作为更复杂情况的一般评论。而且我喜欢基于块的方法!
  • @MartinR 你有addObserverForName:object:queue:usingBlock: 的实现示例吗?非常感谢
【解决方案2】:

为了回答您的直接问题,当您的视图仍在屏幕上时,将永远不会调用 dealloc,除非您不应该直接调用它。

只有在没有指向 viewController 的强指针剩余时才会调用dealloc。

正如 Anoop Vaidya 建议的那样,将 removeObserver 放入 dealloc 并确信 dealloc 在您的 viewController 在屏幕上时不会被调用是完全可行的,如果确实如此......那么你有更大的比移除观察者更重要的问题

编辑:由于我实际上还不能回复 cmets,所以当您的 viewController 不在屏幕上时,它实际上已被释放。当它在屏幕上被回调时,它会被重新实例化。

编辑:我错了

【讨论】:

  • 视图控制器在屏幕外时不会自动释放和重新实例化。当视图在屏幕上时释放视图控制器也是很有可能的,因为视图没有对其视图控制器的强引用。这通常不会发生,尤其是使用 ARC,但如果您要手动将 vc 的视图添加到层​​次结构中,如果 vc 是自动释放的,则很容易发生这种情况。
  • @omz:我不明白你的第二句话。视图控制器在其视图仍然可见的情况下被释放怎么可能发生?当视图控制器位于视图控制器层次结构中的某个位置时,不应该有对视图控制器的强引用吗? - 好的,我刚刚看到你对评论的更新。我只是在考虑 ARC。
  • 糟糕,我以为我在斯坦福的讲座上听说过,但我还是菜鸟
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多