popViewController,dealloc和removeObserver

时间:2013-05-03 06:24:34

标签: ios objective-c xcode uinavigationcontroller nsnotificationcenter

我遇到了从NSNotificationCenter中删除观察者的正确位置的问题

// DetailOfSomethingViewController
@implementation DetailOfSomethingViewController

- (void)viewDidLoad {
    [[NSNotificationCenter defaultCenter] addObserver:self 
                                          selector:@selector(showMoreDetail:) 
                                          name:SOME_NOTIFICATION_NAME 
                                          object:sender];
}

- (void)dealloc {
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

- (void)showMoreDetail:(id)sender {
    [self presentViewController:[[MoreDetailViewController alloc] init] animated:NO completion:nil];
}

在我的测试运行期间,我尝试从导航堆栈中弹出此viewController的实例并将新实例推送到堆栈。我发现从导航堆栈中弹出的实例的dealloc方法不会立即被调用。

因此,在调用dealloc之前的那一刻,如果SOME_NOTIFICATION_NAME已从其源发出,则弹出的实例仍然通过调用showMoreDetail进行侦听和响应(注意:导航堆栈上的那个工作正常)并尝试呈现MoreDetailViewController虽然不在应用程序窗口中。所以这个警告已经提高了。

Warning: Attempt to present <DetailOfSomethingController: 0xac2c3e0> on <MoreDetailViewController: 0xac268f0> whose view is not in the window hierarchy!

我可以检查视图控制器实例的导航堆栈是否存在,但有什么方法可以在弹出时立即删除观察者?我不能将删除代码放在viewDidDisappear或viewWillDisappear中,因为这个控制器必须通知并做一些事情,即使它不是堆栈的topViewController。

此外,在显示另一个视图之前添加要检查的代码必须在此控制器中添加几个位置,因为showMoreDetail不是将执行演示的唯一方法,还有更多类似的方法。

欢迎任何帮助,建议。

此致

2 个答案:

答案 0 :(得分:1)

我的建议是在 viewWillAppear:中将viewController注册为观察者,并在 viewWillDisappear中删除它

这样你的视图只会在它是顶级viewController时响应。

更新:

我认为,当视图显示时,您可以做的是仅注册该通知

- (void)viewWillAppear:(BOOL)animated{

    [super viewWillAppear:animated];
    [[NSNotificationCenter defaultCenter] addObserver:self 
                                          selector:@selector(showMoreDetail:) 
                                          name:SOME_NOTIFICATION_NAME 
                                          object:sender];
}

并以观察者的身份删除视图控制器(仅用于该通知,并且仍然会收听其他通知)

- (void)viewWillDisappear:(BOOL)animated
{
    [super viewWillDisappear:animated];
    [[NSNotificationCenter defaultCenter] removeObserver:self
                                                    name:SOME_NOTIFICATION_NAME
                                                  object:nil]; 

}

答案 1 :(得分:1)

showMoreDetail:中检查UINavigationController的topViewController属性是否等于self,如果只有,则继续。