Swift 类的初始化器
2022-04-19 本文已影响0人
诗颜语
本节主要以class的初始化器讲解,struct 的初始化器与class类似,但不完全相同,而且不会牵扯到继承的问题;
口诀
- 便捷实现靠自身,必要实现靠super,指定实现看需要
介绍
- 类初始化时会调用的代码块,必须在此处完成 未初始化的 非可选类型的 存储属性的赋值操作;
- 使用init关键字修饰,注意是关键字;
分类
- 指定初始化器:可以有多个,如果是基类则自动实现
init(){}
,否则是继承父类的,也可重写父类的。 - 便捷初始化器:可以有多个,使用
convenience
修饰,不能继承重写父类的,实现中必须调用自身的指定初始化器。eg:self.init()
。 - 必要初始化器:可以有多个,使用
required
修饰。
使用注意事项
-
指定初始化器:super只能调用父类的指定初始化器,不可调用超类的。以
HJViewController
为例:
init() {
// 不允许这样写
super.init()
}
//所以以下写法可以,但同样‘不建议’这样写 init() 与超类同名了
init() {
super.init(nibName: nil, bundle: nil)
}
-
便捷初始化器:如果自定义了指定初始化器,则父类的指定初始化器就不能在便捷初始化器中使用。最好不要与所有父类(超类)的初始化器重名,会导致父类(超类)的方法不被调用,还有可能造成循环调用。以
HJViewController
为例:
convenience init() {
self.init(nibName: nil, bundle: nil)
}
- 必要初始化器:有以下几点
-
如果父类实现必要初始化器,而子类没有实现(自定义/重写父类)指定初始化器或必要初始化器,则自动继承,反之则必须实现。
-
基于1. 实现中可不必调用 父类/自身 的指定初始化器。eg:
-
required init?(coder: NSCoder) {
//一般调用super ,亦可自己实现。此示例是因为`HJViewController`父类遵守了NSCoding协议
//super.init(coder: coder)
}
- 如果自身增加必要初始化器,实现中只能调用父类的指定初始化器。eg:
super.init()
作为最终使用的类,在UIViewController中使用的建议
指定初始化器最好只有一个 或者没有
不建议UIViewController
的子类重写父类指定初始化器,或自定义指定初始化器,因为这样做必须要实现required init?(coder: NSCoder)
此‘必要初始化器。
建议使用convenience
修饰初始化器:这种初始化器称为便捷初始化器;便捷初始化器内部必须调用一个指定初始化器。
如果非要在初始化时做点什么的话,如果func viewDidLoad()
不满足,则只能重写下边这个触发条件中提到的指定初始化器。
触发条件
- 外部调用OC:
[[HJViewController alloc]init]
,[[HJViewController alloc]initWithNibName:nil bundle:nil]
。 - 外部调用Swift:
HJViewController()
,HJViewController(nibName: nil, bundle: nil)
。 - 都会走以下指定初始化器。
override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
// self.datas = [1] 未调用父类的指定初始化器 此时对象未初始化完成 self不可用
super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
}
required init?(coder: NSCoder) {
super.init(coder: coder)
}