我有UIViewController
个子类。我有一个常数,我想懒惰负载。为此,我使用了一个函数来设置它的默认值。我在这里有两个init
方法,因为我之前使用它们来设置值。然后我发现我无法调用常用方法来设置值。似乎只有init方法可以设置类的值常量。当我创建函数来设置默认值时,我发现我有一个无限循环,它从init(nibName,bundle)函数重复调用我的函数for goal。我是新手,不知道我做错了什么。
class ViewController: UIViewController {
let goal: Goal =
{
return Goal()
}()
override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?)
{
super.init()
}
required init(coder decoder: NSCoder)
{
super.init()
}
}
答案 0 :(得分:1)
当你覆盖一个方法时,你应该调用这个方法的超级实现。
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个位置设置变量。 示例强>
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(如果存在)。之后,您可以访问自我和呼叫方法。
在Cocoa Framework中,类有多种方法来实例化它们并拥有许多初始化器。示例UIViewController有
init(nibName: String?, bundle: NSBundle?)
和init(coder :NSCoder)
我们如何初始化这个类?
这个解决方案有一个巨大的缺点 - 它不是DRY
您在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 class安全规则,我们无法做到这一点 初始化步骤
代码:
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支持内部类。您可以在类中创建一个类。这样,您可以在类中对某些功能进行分组。这种声音非常适合将初始化方法分组到Factory类中 最后的例子:
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"
}
}