当你重写一个方法时,你应该调用这个方法的超级实现。
required override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?) {
super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
}
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
常let
量值只能在初始化器中设置。如果您有超过 1 个初始化程序,请考虑如何链接它们。拥有 1 个指定的初始化程序和许多便利非常有用。通过这种方式,您只能将变量设置在 1 个位置。例子
class A {
let age: Int
let name: String
let type: String
init(age: Int, name: String, type: String) {
self.age = age
self.type = type
self.name = name
}
convenience init() {
self.init(age: 0, name: "", type: "")
}
convenience init(age: Int) {
self.init(age: age, name: "", type: "")
}
convenience init(age: Int, name: String) {
self.init(age: age, name: name, type: "")
}
在 swift 中,您必须在 init 方法中完全初始化类。这意味着您必须为所有属性设置值并调用 super init(如果存在)。之后,您可以访问 self 和 call 方法。
在 Cocoa 框架中,类有超过 1 种方法来实例化它们并有许多初始化程序。示例 UIViewController 具有
init(nibName: String?, bundle: NSBundle?)
以及init(coder :NSCoder)
我们将如何初始化此类?
- 设置变量值
这个解决方案有一个巨大的缺点 - 它不是DRY
你在 2 个地方有相同的代码。如果您需要更改或修复它,您需要在 2 个地方执行相同的操作。非常糟糕的架构和代码气味。
var name: String
required init(coder aDecoder: NSCoder) {
name = "Name"
super.init(coder: aDecoder)
}
override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?) {
name = "Name"
super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
}
我们能做得更好吗?解决方案看起来很明显 - 在单独的方法中提取名称初始化。但我们不能这样做,因为Swift 类安全规则
Initialization Steps
- 设置所有属性
- 调用 super.init(...)
- 现在您的类和超类都已完全初始化。只有在这里您可以访问 self 并调用 self 上的方法
代码:
required init(coder aDecoder: NSCoder) {
setDefaultName() // Error. Can't access self yet
super.init(coder: aDecoder)
}
func setDefaultName() {
name = "Name"
}
- 默认值
设置变量的默认值。
这看起来更好,因为我们只在一个地方初始化属性。
var name: String = ""
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?) {
super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
}
如果你需要更复杂的逻辑来初始化你的变量,你可以使用闭包。
我不喜欢这样,因为现在你的类变量声明中有逻辑(与函数相同的闭包)。
我们能做得更好吗?我们可以!
var name: String = {
var name = "Name"
// ....
// Other complicated logic
name + " Is Best"
return name
}()
- 工厂方法
最好把这个闭包移到类变量定义之外,
这样我们就可以做类似的事情var name = Factory.defaultName()
Swift 支持内部类。您可以在类中创建一个类。通过这种方式,您可以将一些功能分组到一个类中。这听起来很适合将初始化方法分组到工厂类
最终示例中:
var name: String = Factory.defaultName()
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?) {
super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
}
class Factory {
class func defaultName () -> String {
return "Name"
}
}