正确的loadView实现

苹果的文档没有说什么正确的实施是为loadView。

我发现,如果你实现像这样的loadView:

- (void)loadView { self.view = [[UIView alloc] init]; } 

…然后你会得到不同的行为,如果你根本没有实现它。 特别是,在一个20行的项目中,我发现viewWillAppear被调用self.view的零大小的框架 – 除非你使用苹果的默认版本的loadView。

在Google上看,有很多“教程”提供了明显错误的loadView实现 – 例如,强制将大小设置为(320,480),因为教程作者“发现它可以工作,如果我这样做”。

我想知道正确的实施应该是什么。

注意:在我上面的示例中,我将它添加到AppDelegate中的视图层次结构中,如下所示:

 [self.window addSubview:(UIViewController*).view]; 

我相信,在UINavigationController或UITabBarController的存在下,苹果会做一些额外的魔术 – 作为一个副作用 – 导致单行loadView实现工作正常。 但是我想把它写得正确,所以它总是有效的!

注意:我已经尝试在根视图上设置自动调整屏蔽,但它不会改变发生的事情:

 - (void)loadView { self.view = [[UIView alloc] init]; self.view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; } 

-loadView默认实现创build视图或加载NIB 。 据我所知,在-loadView 创build时,无法知道视图的最终大小。 所以默认的视图尺寸被设置为[[UIScreen mainScreen] bounds] 。 这是因为在-viewDidLoad和其他方法中使用零帧视图工作可能很困难。

您的单行实现可能如下所示:

 - (void)loadView { self.view = [[UIView alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; } 

您不需要设置自动调整屏蔽,因为您不知道视图将在什么情况下显示。 调用者负责设置你正确的框架,自动调整掩码和类似的外部属性 (我这样称呼他们)。

想象一下在UINavigationController方法中:

 // we are pushing new VC, view is accessed for the first time pushedVC.view.frame = CGRectMake(...); 

这是设置正确的框架,但你的-loadView被调用之前 -setFrame: 所以在-viewDidLoad期间你有临时的非零帧,只是为了能够设置子视图和内部自动修复。 在此之后,正确的框架设置给你,并在-viewWillAppear:你有最后的框架。

首先,没有“默认”的loadView实现…该方法是专门为您覆盖。 我同意苹果的文档可能有点不清楚。 但是,当访问导航控制器的视图并且不存在视图(例如: UIView *view = viewController.view )时,默认情况下调用loadView 。 它也可以手动调用。 但是在任何情况下, loadView都不会有正确的维度,也就是说,事实上是不可能的。 调用loadView是为了使父视图控制器能够首先获取视图,以便能够适当地调整它的大小。 然后一旦它获得视图,它调用viewDidLoad 。 这是他们可以使用的唯一代码path,因为视图可以从loadView方法或笔尖加载,并且当从nib加载视图时,它们必须提供一个额外的设置位置。 最后,父控制器将调整视图的大小,并调用viewWillAppear只有当视图实际上出现。 例如,如果您在屏幕外的navController上推控制器,则不会调用viewWillAppear直到将navController本身放置在屏幕上。 这样做是因为在控制器实际可见的情况下运行该代码没有意义。 这也是为什么你只能在viewWillAppear方法中获得正确的尺寸。

现在,你注意到如果你添加一个控制器到一个标准的控制器,这些东西都不会发生。 这是因为视图控制器并不是真正意图包含其他视图控制器。 现在在iOS 5中,他们明确地支持使用Container View控制器…它本质上是一个视图控制器,它被devise成包含其他视图控制器。 他们在iOS 5中增加了一些“方便”的方法来解决这个问题,但这并不是必须的。 所有这一切都是:如果你想添加一个视图控制器到另一个,你将不得不手动设置所有适当的调用子视图控制器(所有加载方法,旋转事件,内存警告等)。 换句话说,你必须build立你自己的容器视图控制器。 但是,当你这样做的时候,要记住我之前说的代码path。 按照与苹果相同的顺序调用子控制器方法非常重要,否则这些方法将无法正常工作。

以下是一些信息链接: http : //developer.apple.com/library/ios/#documentation/uikit/reference/UIViewController_Class/Reference/Reference.html – 向下滚动到:实现一个容器视图控制器

同样在这里为视图控制器的生命周期,这将帮助你找出哪些调用需要按顺序: http : //developer.apple.com/library/ios/#featuredarticles/ViewControllerPGforiPhoneOS/ViewLoadingandUnloading/ViewLoadingandUnloading.html# // apple_ref / DOC / UID / TP40007457-CH10-SW1

我build议阅读整个视图控制器编程指南….你可以从那里闪烁大量的信息: http : //developer.apple.com/library/ios/#featuredarticles/ViewControllerPGforiPhoneOS/Introduction/Introduction.html#/ / apple_ref / DOC / UID / TP40007457-CH1-SW1