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 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

这个方法在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中都调用一下,这样就保证了无论你是通过什么方式创建的控件,代码都能起到作用。

你可能感兴趣的:(iOS initWithFrame、initWithCoder、awakeFromNib的区别解析)