• iOS initWithFrame、initWithCoder、awakeFromNib的区别解析


    当我们需要自定义一个View控件时,会有 initWithFrame、initWithCoder、awakeFromNib 这三个系统方法,关于这三个方法何时调用,如何调用,有时候可能很多人会弄混淆。 

    下面我会就理论结合代码举例来说明一下:

    1、initWithFrame

    - (instancetype)initWithFrame:(CGRect)frame
    {
        self = [super initWithFrame:frame];
        if (self) {
            NSLog(@"initWithFrame");
            [self initViews];
        }
        return self;
    }

    这个方法是当控件不是从xib、storyboard中创建时,会调用这个方法,比如:

     XibShow *xib = [[XibShow alloc] initWithFrame:CGRectMake(0, 330, KScreenWidth, 100)];
     [self.view addSubview:xib];

    这里我直接用  [XibShow alloc] initWithFrame  来创建控件,所以,这里自定义控件内,只会走  initWithFrame 方法,其余两个不会走。

    2、initWithCoder

    - (instancetype)initWithCoder:(NSCoder *)coder
    {
        self = [super initWithCoder:coder];
        if (self) {
            NSLog(@"initWithCoder");
            [self initViews];
        }
        return self;
    }

    当控件是从xib、storyboard中创建时,就会调用这个方法。

    概括的理解就是:你的view或cell在xib或storyboard上有体现,比如直接用xib创建的,或是拉控件关联已有类等。

    而且,即使我们自定义的view是纯代码,没有xib,但我们在vc的xib里引用了,效果是一样的。

    比如,这两种方式创建的自定义view,只要我们有在xib或storyboard里引用过,就都会执行initWithCoder和awakeFromNib

    3、awakeFromNib

    -(void)awakeFromNib{
        NSLog(@"awakeFromNib");
        [super awakeFromNib];
        [self initViews];    
    }

    这个方法在initWithCoder:方法后调用 ,顺序是:initWithCoder  -> awakeFromNib (下面会有代码截图)

    - 可以这么来理解:

    一开始经过initWithCoder创建出来的控件是死的,然后通过awakeFromNib来唤醒,所以这会有一个先后的调用顺序。

    下面会有一个具体的示例:

    1、创建一个vc,在storyboard上关联界面,在界面上新增一个view,关联我们的自定义view:XibShow。

    2、在vc里,再额外用代码新增一个自定义view控件,add到另一个位置。

    这样,运行出来的结果如下:

    其中:打印顺序如上图所示。

    可以发现:

    1、在viewDidLoad之前,由于是storyboard上创建的类,会先执行好,且会顺序走 initWithCoder、awakeFromNib两个方法

    2、到viewDidLoad之后,执行到用代码创建的view,只会走 initWithFrame 方法

    PS:这里还有个小细节:我在storyboard上托控件创建的类,即使我给了背景色,但执行出来,还是以自定义view本身的背景色为准。

    (可以看上图,开始设的灰色,但运行出来还是红色)

    最后总结:

    1、initWithFrame只适用纯代码创建时调用,不涉及xib或storyboard。

    2、initWithCoder、awakeFromNib是从xib、storyboard中创建时会调用。

    3、所以一般来说,为了安全起见,初始化控件的代码我们写在一个方法里面(类似我上面的initViews方法),然后我们分别在initWithFrame和initWithCoder中都调用一下,这样就保证了无论你是通过什么方式创建的控件,代码都能起到作用。

  • 相关阅读:
    lucene复合条件查询案例——查询name域 或 description域 包含lucene关键字的两种方式
    谈谈你对spring的理解?
    模拟Http请求的几种常用方式
    idea破解教程
    Pycharm 或者 idea 注册码 (亲测可用)
    超详细虚拟机工具和Centos7 Linux系统安装
    严重: Error loading WebappClassLoader context:异常的解决方法(转)
    spring cloud 笔记记录
    近一周学习之-----vue学习快乐之旅(1)
    近一周学习之-----vue开发工具visual studio code
  • 原文地址:https://www.cnblogs.com/yajunLi/p/6344023.html
Copyright © 2020-2023  润新知