关于loadView

Creates the view that the controller manages.
You should never call this method directly. The view controller calls this method when its view property is requested but is currently nil. This method loads or creates a view and assigns it to the view property.
If the view controller has an associated nib file, this method loads the view from the nib file. A view controller has an associated nib file if the nibName property returns a non-nil value, which occurs if the view controller was instantiated from a storyboard, if you explicitly assigned it a nib file using the initWithNibName:bundle: method, or if iOS finds a nib file in the app bundle with a name based on the view controller's class name. If the view controller does not have an associated nib file, this method creates a plain UIView object instead.
If you use Interface Builder to create your views and initialize the view controller, you must not override this method.
You can override this method in order to create your views manually. If you choose to do so, assign the root view of your view hierarchy to the view property. The views you create should be unique instances and should not be shared with any other view controller object. Your custom implementation of this method should not call super.
If you want to perform any additional initialization of your views, do so in the viewDidLoad method.

- (void)loadView;// This is where subclasses should create their custom view hierarchy if they aren't using a nib. Should never be called directly.


- (void)viewDidLoad;// Called after the view has been loaded. For view controllers created in code, this is after -loadView. For view controllers unarchived from a nib, this is after the view is set.


永远不要主动调用 loadView 方法

ViewController 会在 view 的属性被请求且当前 view 为 nil 时调用 loadView。

如果你是用 xib 创建 view 并初始化 ViewController,意味着你要使用 initWithNibName:bundle: 方法,则不要覆盖 loadView 方法。

如果你是手动创建 view,就要覆盖该方法。

永远不要在覆盖 loadView 方法时使用 [super loadView]

loadView 方法是查看你有木有 xib,有的话就用 xib 加载基本信息,木有的话就会创建一个空白的 UIView,然后把它作为这个 ViewController 的 view。

所以你覆盖这个函数的时候,也按照这个方式是实现就好了。只不过你不是创建一个空白的 UIView,那也没有意义。你创建一个你想要的 UIView,一定要注意这个 UIView 实例必须是给这个 ViewController 独享的(不能被其他实例共享),否则会出问题的。

在 loadView 中实例化 view,在 viewDidLoad 中自定义 view

你只需要在 loadView 时创建 view,不要对它做什么自定义的。

在内存紧张时,程序会调用 viewDidUnload 来释放内存,这个方法是与 viewDidLoad 相对的。当程序内存不那么紧张,且需要用到这个 ViewController 时,则会再次调用 viewDidLoad。

viewDidLoad 和 viewDidUnload 中的操作是相对的。


无论是从xib文件中加载视图,还是自己创建视图,viewDidLoad方法都会被调用,而且都是在视图已经被加载后调用,所以这里可以明确的一点是,任何UI控件的创建都不应该在viewDidLoad方法中被实现,因为这是xib文件或者loadView方法的任务。viewDidLoad只是通过nib或者loadView方法加载视图的一周拓展和补充机制,比如一些不方便通过nib设置的属性或是临时需要进行处理的控件内容。

至于loadView方法和xib文件的关系,个人的理解是:真正的UI控件的创建,都是要通过调用loadView中的代码来实现的,只不过在xib文件中,这些代码以xml格式的文档被保存,并且苹果通过storyboard解析这个xml文档,形成了一个可视化的图形界面。这是两者的共同点,至于不同点,官方文档中的解释已经很清楚了,一旦调用了loadView方法就意味着不是用nib文件。这就意味着loadView和xib文件不兼容。loadView具有更高的优先级。

下面通过几个实验来证明以上观点。
实验1:
创建一个空的工程文件,在viewDidLoad函数中写入简单的一行代码:

-(void)viewDidLoad {

[super viewDidLoad];

NSLog(@"123");

}

实验结果:运行程序后发现:控制台输出一行结果“123”。模拟器显示一个纯白色的界面。
实验分析:控制台的结果非常容易理解。但是我们并没有创建一个UIView或者设置它的背景颜色,系统是怎么创建我们在模拟器中看到的内容的呢?
答案是,如果我们不实现loadView方法,系统会默认我们不适用自定义的方式创建view而是从nib文件中加载。这时候就回去storyboard或者其他相应的nib文件中去寻找加载视图的代码。由于默认的ViewController类在main.storyboard中有自己的nib文件,所以可以成功的加载一个UIView。

实验2:
实现一个空的loadView方法:

- (void)loadView {

}

实验结果:运行程序后发现,控制台输出两行“123”,模拟器黑屏。
实验分析:模拟器黑屏非常容易理解,因为我们实现了loadView方法,编译器以为我们要自定义一个UIView对象,从而去执行loadView方法中的代码,试图创建一个UIView,但是显然这样做会失败,所以得到一个黑色的(没有任何内容)的界面。至于为什么viewDidLoad方法会被调用两次,原因并不清楚(希望读到此处的大牛留言指教)。

实验三:
实现完整的loadView方法:

- (void)loadView {

self.view = [[UIView alloc] initWithFrame:[UIScreen mainScreen].applicationFrame];

self.view.backgroundColor = [UIColor whiteColor]; 

}

实验结果:同实验1的结果
实验分析:实现了一个完整的UIView的创建过程,与通过nib文件创建非常类似。

通过以上几个实验得出以下结论:
1.如果想要通过自定义的代码创建UIView,把这些代码都写入loadView方法里面去。
2.希望通过nib文件创建UIView的话,不要重写loadView方法。
3.viewDidLoad方法被执行两次很有可能是重写了一个不完整的loadView方法导致的 。


=================================================================================================

UIViewController的loadView

用UIViewController有一段时间了,才发现以前对loadView的理解完全不到位。

假如我们用Xcode新建一个View-based Application,在ViewController.m中加上

- (void) loadView {
NSLog(@"loadView Called");
}

再增加viewDidLoad,按照一般的情况,我们会有这样的Code

- (void) viewDidLoad {
[super viewDidLoad];
UIButton *customButton = [UIButton buttonWith.....
......
[self.view addSubView:customButton];
}

现在打开MainWindow.xib,删掉其中的ViewController,并在AppDelegate.m的

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions;

里增加ViewController的初始化

viewController = [[XXXViewController alloc] init];

编译运行就有问题了。Console中不断的输出loadView Called!

仔细的阅读loadView的文档,才知道loadView不是这么用的。

loadView在每一次使用self.view这个property,并且self.view为nil的时候被调用,用以产生一个有效的self.view。这个接口原本是为了让我们自定义view用的。在不被subclass实现的情况下,也就是[super loadView]的效果,应该就是产生了一个有效的view,也就是一个空白的view。

在上面这种情况下,loadView被实现为空(只有一条打印语句),而且我们没有通过XIB初始化ViewController,所以在viewDidLoad被执行时,self.view是为nil的。所以在执行[self.view addSubView:customButton]时,loadView被调用,用来产生一个有效的view,使得self.view不再为nil。罢特,我们错了(-_-!)。我们的loadView什么也没有做,于是就出现了上面的情形,不断的调用一个什么都不做的loadView….

当然,我们只要在loadView中增加一句[super loadView]就没有问题了。但这并不是Cocoa的设计者所期望的。

loadView仅仅应该在开发者希望自行通过编码而不是Interface Builder定制view的时候被实现,而且不应该在其中调用[super loadView],你的loadView中应该有self.view = …这样的行为。

如果仅仅是想要在当前view上增加一些UIButton或是UILabel,应该在viewDidLoad里去做,此时不要实现自己的loadView。



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值