【问题标题】:popViewController, dealloc and removeObserverpopViewController、dealloc 和 removeObserver
【发布时间】:2013-05-03 06:24:34
【问题描述】:

我在从 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 不是唯一可以进行呈现的方法,还有更多类似的方法。

欢迎任何帮助、建议。

问候

【问题讨论】:

    标签: ios objective-c xcode uinavigationcontroller nsnotificationcenter


    【解决方案1】:

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

    【讨论】:

    • 感谢您的评论,但我在我的问题中表示,添加一组代码来检查此视图控制器是否存在于导航堆栈中不是首选选项。我实际的视图控制器正在侦听和响应 10 多个通知。所以,我更喜欢从通知中心删除它。
    【解决方案2】:

    我对你的建议是在 viewWillAppear: 中将你的 viewController 注册为观察者,然后在 viewWillDisappear:

    中将其删除

    这样你的视图只会在它是顶部视图控制器时响应。

    更新:

    我认为您可以做的是仅在视图出现时注册该通知

    - (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]; 
    
    }
    

    【讨论】:

    • 感谢您的评论,但我的实际视图控制器还在导航堆栈中侦听和响应其他通知消息,无论是否是顶视图控制器。所以,一旦它不再存在,我更愿意将它从通知中心中删除。
    猜你喜欢
    • 1970-01-01
    • 2012-12-04
    • 1970-01-01
    • 2014-03-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多