UINavigationController 子类未按预期调用 willShowViewController

Posted

技术标签:

【中文标题】UINavigationController 子类未按预期调用 willShowViewController【英文标题】:UINavigationController subclass not calling willShowViewController when expected 【发布时间】:2013-05-13 18:49:06 【问题描述】:

我已经使用ECSlidingViewController 实现了一个带有样式菜单幻灯片的应用程序

目前我有以下设置: ECSlidingViewController 的初始视图控制器子类。这处理顶视图控制器(屏幕上显示的主视图)和作为菜单的 underLeftController 的推送。

菜单是一个表格视图控制器子类,当单击一行时,一个新的顶视图控制器被推入堆栈。

根据previous question,我使用一个包含单个根视图控制器的导航控制器(子类)。每次选择一行时,导航控制器的一个新实例都会加载一个不同的视图控制器,旧的 dealloc'd。例如:

// Check if the settings view is currently displayed if it is just reset the top view else load it to the topviewcontroller.
                UINavigationController *navController = (UINavigationController *)self.slidingViewController.topViewController;
                UIViewController *VC = navController.topViewController;
                if ([VC isKindOfClass:[MESSettingsViewController class]]) 
                    [self.slidingViewController resetTopView];
                 else 
                    MESMainNavViewController *mainNavController = [[MESMainNavViewController alloc] initWithRootViewController:[self.storyboard instantiateViewControllerWithIdentifier:@"SettingsVC"]];

                    __weak typeof(self) weakSelf = self;

                    [self.slidingViewController anchorTopViewOffScreenTo:ECRight animations:nil onComplete:^
                        CGRect frame = self.slidingViewController.topViewController.view.frame;
                        self.slidingViewController.topViewController = mainNavController;
                        self.slidingViewController.topViewController.view.frame = frame;
                        [weakSelf.slidingViewController resetTopViewWithAnimations:nil onComplete:^
                            [weakSelf updateCurrentCell];
                        ];
                    ];
                

目前一切正常。我遇到的问题是登录顺序。如果用户注销,则会以模态方式推送不同的导航堆栈。一旦用户完成成功登录,就会发出通知。这是由初始视图控制器(从上面)接收的:

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

然后,该方法处理将用户推送到相关子类导航控制器的新实例,以主控制器为根。

// If the view controller is not home send them to home
UINavigationController *navController = (UINavigationController *)self.topViewController;
UIViewController *VC = navController.topViewController;
if (![VC isKindOfClass:[MESHomeViewController class]]) 
    UIStoryboard *storyboard;

    if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone) 
        storyboard = [UIStoryboard storyboardWithName:@"MainStoryboard_iPhone" bundle:nil];
     else if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) 
        storyboard = [UIStoryboard storyboardWithName:@"MainStoryboard_iPad" bundle:nil];
    

    MESMainNavViewController *mainNavController = [[MESMainNavViewController alloc] initWithRootViewController:[self.storyboard instantiateViewControllerWithIdentifier:@"HomeVC"]];

    self.topViewController = mainNavController;
    [self resetTopView];


问题似乎出在以下部分:

MESMainNavViewController *mainNavController = [[MESMainNavViewController alloc] initWithRootViewController:[self.storyboard instantiateViewControllerWithIdentifier:@"HomeVC"]];

self.topViewController = mainNavController;

当创建导航控制器的这个新实例时,代理方法willShowViewController 似乎没有被调用?我不知道为什么,当通过菜单表视图更改控制器时它会调用它并且它使用相同的方法来创建,有什么想法吗?

【问题讨论】:

【参考方案1】:

苹果文档指出

UINavigationControllerDelegate 协议定义了方法 a 导航控制器委托可以实现改变行为 当视图控制器从堆栈中推送和弹出时 导航控制器。

所以,我认为只有在将视图控制器推送到导航堆栈或从导航堆栈弹出视图控制器时,才会调用方法 willShowViewController

【讨论】:

我同意,但是当正在创建导航控制器的新实例时,它正在推动控制器。当菜单系统按照问题中的代码工作时,每次创建一个新实例并调用 push 方法。只是在第二部分似乎没有被调用? 是的,我仔细检查了一下,似乎initWithRoot 将视图控制器推送到堆栈上,但我不确定此推送是否会调用委托方法。我想到的另一件事是,您在哪里设置导航控制器委托? uinavigationcontroller是自己的delegate,目前设置在MESMainNavViewController的viewDidLoad中

以上是关于UINavigationController 子类未按预期调用 willShowViewController的主要内容,如果未能解决你的问题,请参考以下文章

自定义 UINavigationController UIToolbar 子类

UINavigationController 子类和推送 Segue

iphone UIViewController 基子类未在 UINavigationController 中显示视图

以编程方式在 UINavigationController 中设置 UINavigationBar 的自定义子类

UINavigationController 子类未按预期调用 willShowViewController

来自 tableViewController 子类的 UINavigationController pushViewController