美文网首页iOS
iOS控制器View加载顺序详细版

iOS控制器View加载顺序详细版

作者: 七里田间的守望者 | 来源:发表于2017-10-27 14:43 被阅读556次

    控制器声明周期

    //通过nib问价初始化触发
    - (instancetype)initWithCoder:(NSCoder *)aDecoder
    
    //nib文件被加载的时候,会发送一个消息到nib文件中的每一个对象
    - (void)awakeFromNib
    
    //开始加载视图控制器自带的view
    - (void)loadView
    
    //视图控制器的view被加载完成
    - (void)viewDidLoad
    
    //视图控制器的view将要显示在window上
    - (void)viewWillAppear:(BOOL)animated
    
    //视图控制器的view开始更新Autolayout
    - (void)updateViewConstraints
    
    //视图控制器的view开始更新内容视图的位置
    - (void)viewWillLayoutSubviews
    
    //视图控制器的view已经更新内容视图的位置
    - (void)viewDidLayoutSubviews
    
    //视图控制器的view已经显示到window上
    - (void)viewDidAppear:(BOOL)animated
    
    //视图控制的view将要从window上消失
    - (void)viewWillDisappear:(BOOL)animated
    
    //视图控制器的view已经从window上消失
    - (void)viewDidDisappear:(BOOL)animated
    

    加载过程:
    1 一般情况下调用 init方法或者调用initWithNibName方法实例化UIViewController, 不管调用哪个方法都为调用initWithNibName(方法定义如下)

    • -(id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil

    • 接着会调用loadView方法来生成UIViewController.view

    • - (void)loadView

    • 下面来简单说下loadView底层

      • 判断下有没有指定storyboard,如果有,就去加载storyboard描述的控制器的view

      • 判断下有没有指定nibName,如果有,就去加载nibName描述的控制器的view

      • - (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil

      • 如果判断有没有指定nibName,[self nibName]

      • 判断下nibName是否为空,如果为空,他会尝试找下有没有跟控制器同名,但是不带Controller的xib

      • 跟控制器同名的xib,nibName = ViewController,但是这一步有条件,前提条件你没有重写loadView

      • 如果都没有找到,直接创建默认控制器的view

    - (void)awakeFromNib;

    • 这个方法用的时候,outlet还没有连接起来,是view Controller刚从storyboard建的时候,没有完全建好,不过可能有一些事情要在这个方法里面完成,比如splitViewDelegate,需要在非常早期完成。然后调用 viewDidLoad方法
      - (void)viewDidLoad

    • 如果loadView不能生成UIViewController.view系统将会反复调用loadView及viewDidLoad方法, 并且最终调用[super loadView] 方法返回UIViewController.view
      然后依次调用如下2个方法, 这2个方法也十分重要, 在UINavigationController的POP操作后有时将要显示的UIViewController中的View并没有释放(也有可能释放掉) , UIViewController将不会调用上面的三个方法(initWithNibName,loadView,viewDidLoad) 而会调用下面这2个方法

    • - (void)viewWillAppear:(BOOL)animated;

    • - (void)viewDidAppear:(BOOL)animated;
      紧接着调用下面两个方法view中frame值布局,使子控制器的frame值更加准确

    • - (void)viewWillLayoutSubviews

    • -(void)viewDidLayoutSubviews

    • 页面消失的方法

    - (void)viewWillDisappear:(BOOL)animated;
    - (void)viewDidDisappear:(BOOL)animated;
    - (void)viewWillUnload;//iOS5.0添加- (void)viewDidUnload;
    - (void)dealloc;

    • 控制器View一些方法的区分

      • viewDidLoad其实没什么可混淆的,无论通过什么途径加载(Xcode或者IB,这里的加载属于实例化)完view后肯定会执行这个方法.
      • - loadView需要分两种情况.
        • 当你通过Xcode实例化一个类的时候就需要自己在controller中实现这个方法.
        • 而在IB中实例化就不需要实现它.
        • - initWithNibName这个方法是在controller的类在IB中创建,但是通过Xcode实例化controller的时候用的.
    • awakeFromNib这个方法是一个类在IB中被实例化是被调用的.

    • 看了帖子发现大家都推荐使用viewDidLoad而不要使用awakeFromNib,应为viewDidLoad会被多次调用,

    • 而awakeFromNib只会当从nib文件中unarchive的时候才会被调用一次.

    • 实际测试中发现,当一个类的awakeFromNib被调用的时候,那么这个类的viewDidLoad就不会被调用了,这个感觉很奇怪.

    • - initWithCoder是一个类在IB中创建但在Xcode中被实例化时被调用的.

    • 比如,通过IB创建一个controller的nib文件,然后在xocde中通过initWithNibName来实例化这个controller,那么这个controller的initWithCoder会被调用.

    • - awakeFromNib 当.nib文件被加载的时候,会发送一个awakeFromNib的消息到.nib文件中的每个对象,每个对象都可以定义自己的awakeFromNib函数来响应这个消息,执行一些必要的操作。也就是说通过nib文件创建view对象是执行awakeFromNib

    viewDidLoad 当view对象被加载到内存是就会执行viewDidLoad,所以不管通过nib文件还是代码的方式创建对象都会执行viewDidLoad

    相关文章

      网友评论

        本文标题:iOS控制器View加载顺序详细版

        本文链接:https://www.haomeiwen.com/subject/ttwrpxtx.html