1.如果使用代码的方式创建控件,那么在创建时一定会调用initWithFrame:
方法;如果使用xib/storyboard方式创建控件,那么在创建时一定会调用initWithCoder:
方法。
2.在initWithCoder:
里面访问属性,比如self.button
,会发现它是nil的,因为此时自定义控件正在初始化,self.button可能还未赋值(self.button是一个IBOutlet,IBOutlet本质上就相当于Xcode找到这个对应的属性,然后UIButton button = … , [self.view addSubview: button]这种操作,而这一切的操作都是相当于在CYLViewview = [[CYLView alloc] initWithCoder: nil]方法之后执行的。上面的代码就相当于用代码的方式实现Xcode在storyboard中加载CYLView),所以如果在这个方法中进行初始化操作是可能会失败的。
3.所以建议在awakeFromNib
方法中进行初始化的额外操作。因为awakeFromNib
是在初始化完成后调用,所以在这个方法里面访问属性(IBOutlet)就可以保证不为nil。
4.
通过xib的方式创建的自定义控件,需要设置IBOutlet属性,虽然会调用initWithCoder:
方法,但是调用这个的方法的时候IBOutlet属性还未设置好,所以在这个方法中访问属性将会是nil。而在awakeFromNib
中,IBOutlet已经初始化完毕,所以在这个方法中初始化不会失败。
如果通过initWithFrame:
方法,说明是通过代码创建的自定义控件,它的属性并不是IBOutlet的,所以不存在未完成IBOutlet的属性未初始化完这种情况。所以在initWithFrame:
方法中访问一些属性是没有问题的。但是应该注意,如果是通过init
方法创建的自定义控件也会调用initWithFrame:
方法,但是此时的self.frame
是没有被赋值的(在掉用这个方法的时候并没有设置控件的大小),如果这种情况下使用self.frame
是没有值的。注意这种情况。