将视图控制器推入导航控制器后,不会触发viewDidLoad(和loadView)

问题描述 投票:4回答:6

在将viewController推入导航控制器之后,viewController的视图不会被加载。

这是我的代码片段。

- (void)myMethodInClassA {
    // window's root view controller is navigation controller
    UINavigationController *naviCtrl = (UINavigationController*)[UIApplication sharedApplication].keyWindow.rootViewController;
    MyViewController *myVC = [[MyViewController alloc] initWithNibName:@"MyViewController" bundle:nil];
    [naviCtrl pushViewController:myVC animated:NO];

    // at this point, myVC's view is NOT loaded
}

当我打电话给myMethodInClassA时,myVC的viewDidLoad被称为AFTER,该方法返回。我希望在调用导航控制器的pushViewController:animated:之后和myMethodInClassA返回之前加载myVC的视图。

何时加载了视图控制器的视图? Apple的文档只是说它在首次访问时已加载。这有点模棱两可。为什么导航控制器的pushViewController:访问视图控制器的视图?

附:抱歉最初的含糊不清的问题。

ios uiviewcontroller uinavigationcontroller viewdidload
6个回答
8
投票

将视图控制器(VC)推送到导航控制器的堆栈使VC成为导航控制器(它是容器视图控制器)的子视图控制器。创建这样的子父关系是一个独特的步骤,它不会立即加载子VC的视图。而是容器VC稍后加载视图。我认为没有明确规定“后来”意味着什么 - 通常是当容器VC决定将子VC的视图集成到容器VC的视图层次结构中的时候。但基本上它只是由容器VC的实施自行决定。

话虽如此,任何人都可以通过简单地访问VC的view属性来强制加载VC的视图。例如,在您的代码中,您可以添加此行

myVC.view;

这将引发loadView然后viewDidLoad MyViewController

但是,在您的情况下,如果MyViewController需要对与容器VC关联的事件做出反应,那么最好在MyViewController中覆盖以下方法中的一个(或两个?):

- (void) willMoveToParentViewController:(UIViewController*)parent
{
    // write your code here
}

- (void) didMoveToParentViewController:(UIViewController*)parent
{
    // write your code here
}

但是,您需要注意,当willMoveToParentViewController从其父导航控制器的堆栈中弹出时,也会调用didMoveToParentViewControllerMyViewController。您可以通过检查parentnil参数来检测到这种情况。


2
投票

(斯威夫特2)由于这个问题没有得到接受的答案......

我最终做的是在子视图控制器上创建一个便利初始化:

convenience init() {
    self.init(nibName: "ChildViewController", bundle: nil)
    //initializing the view Controller form specified NIB file
}

并在parentViewController的viewDidLoad()中:

let commentsView = CommentsViewController()
self.addChildViewController(commentsView)
self.momentsScrollView.addSubview(commentsView.view)
commentsView.didMoveToParentViewController(self)

1
投票

如上所述,当推送视图时,viewDidLoad会被调用一次,您可能希望在viewWillAppear或viewDidAppear中执行您的操作。


0
投票

如果ViewController已经在navigationController堆栈中被推送,那么将不会再次调用ViewDidLoad方法。第一次推送ViewController时,将调用viewDidLoad。因此,如果您需要每次都执行某些功能,那么请在viewWillAppear方法中实现它,因为每次推送viewController都会调用它。

希望它能帮到你。


0
投票

你推动第一个tym的视图控制器吗?如果是,则只调用控制器的viewDidLoad(),如果它已经被推,这不是第一个tyn,那么将调用viewWillAppear()。(或)如果你是每个tym你做一个新的实例,然后调用viewDidLoad()。


热门问题
推荐问题
最新问题