自定义控件初始化中常见的几种错误(指定构造器和便利构造器)
截图:
意思是:
1.没有添加重写符override
(重写父类方法)
2.没有重写initWithCoder方法。(此方法只对应初始化是从xib,执行代码只的是,未从xib初始化)
意思是:为初始化父类的init方法
意思是:必须代理初始化自己的方法
意思是:不认识此类型的Default
意思是:禁止调用此初始化方法
意思是:属性label没有在父类初始化方法调用之前初始化
看到这里是不是有种崩溃的心情,别着急,对于OC和Swift的初始化,苹果官方给了一些很合理的解释,请点开这里:https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Initialization.html
定义Swift初始化方法,必须遵循三条规则:
1.指定构造器必须调用它直接父类的指定构造器方法
2.便利构造器必须调用同一类中定义的其他初始化方法
3.便利构造器在最后必须调用一个指定构造器。
图形说明:
便利构造器 前面加convenience
指定构造器什么都不用加,系统初始化方法 要加override
和OC一样,未初始化时,属性是不被赋值的,因为其内存空间不存在
1.第一阶段,是实例的所有属性被初始化
2.第二阶段,实例的所有属性可以再次的调整以备之后的使用
Swift的编译器会对初始化的方法进行安全地检查已保证实例的初始化可以被安全正确的执行:
1.指定构造器必须要确保所有被类中提到的属性在向上调用父类的指定构造器前被初始化,之后才能将其他构造任务移交给父类的中的构造器。
2.指定构造器必须先向上调用父类中的构造器,然后才能为任意属性赋值
3.遍历构造器必须线调用同一个类中的其他构造器,然后再为属性赋值
4.构造器在第一个阶段构造完成之前,不能调用其他任何实例方法,不能读取实例属性的值,self不能被引用
在这里解释初始化所谓的第一阶段:
初始化的第一个阶段:
1.某个指定构造器或便利构造器被调用
2.完成新的实例内存的分配,但此时内存还没有被初始化
3.指定构造器确保其所在类引入的所有存储型属性都已赋值。存储型属性所属的内存完成初始化。
4.指定构造器将调用父类的构造器,完成父类属性的初始化
5.这个调用父类构造器的过程沿着构造器链条一直往上执行,直到到达构造器料条的最顶部(重复1—4步骤)
6.当到达了构造器链条的最顶部,且已确保所有实例包含的存储型属性都已经赋值。这个实例的内存才会被认为已经完全初始化了
注意:
1。子类的便利构造器首先会被调用,此时便利构造器还不能修改子类的任何属性。
2.便利构造器会调用子类中的指定构造器,指定构造器(子类)要确保所有的属性都已赋值,完成所属内存的初始化
3.接着会指定构造器(子类)会调用父类中的指定构造器,完成父类属性所属内存的初始化,直到达到构造器链条的最顶部,所有的属性以及内存被完全初始化,然后进入第二阶段
便利构造器内存未被初始化,不能修改属性
1.从顶部构造器沿着链条一直向下,每个构造器链条中类的指定构造器都有机会一步定制实例。构造器此时可以访问self,修改它的属性并调用实例方法等等
2.最终,任意构造器链条中的便利构造器可以有机会定制实例和使用self
1.如果子类没有定义任何指定构造器,那么会默认继承所有来自父类的指定构造器
5.指定构造器必须要确保所有被类中提到的属性在代理向上调用父类的指定构造器前被初始化,之后才能将其他构造任务交给父类的构造器