iOS ViewDidLoad 执行多次

之前在写一个加载等待动画demo的过程中,遇到一个问题,发现viewDidload方法被不断调用,查看了这两个方法的官方解释后找到了错误原因和解决方法。

首先来看UIViewController.h文件中对viewDidLoad方法的解释:

- (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方法的解释:

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

无论是从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方法导致的 。

温馨提醒:不要声明与系统方法(或变量)同名的变量,这样容易导致会错误调用系统的方法;我的viewDidLoad被重复调用就是因为声明了一个loadView变量,导致viewDidLoad方法被重复调用。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 7、不使用IB是,下面这样做有什么问题? 6、请说说Layer和View的关系,以及你是如何使用它们的。 1.首先...
    AlanGe阅读 736评论 0 1
  • 前言: 这部分内容,对于大部分人来说使用起来可能已经非常熟练,但是涉及到的细节还是挺多的,对于新开发者可能不是...
    饶鹏伟阅读 1,020评论 1 5
  • UI viewcontroller的一些方法的说明viewDidLoad,viewWillDisappear, v...
    b485c88ab697阅读 3,609评论 0 22
  • *面试心声:其实这些题本人都没怎么背,但是在上海 两周半 面了大约10家 收到差不多3个offer,总结起来就是把...
    Dove_iOS阅读 27,227评论 30 472
  • 爱情来时很美,走时很伤—— 骄傲是我最后的姿态,你走,我不哭也不挽留—— 没有告别的再见 “你在哪里,我已经上车了...
    东方笑笑阅读 529评论 0 1