带默认常量值的Swift init无限循环
我有带默认常量值的Swift init无限循环,swift,uiviewcontroller,class-constants,Swift,Uiviewcontroller,Class Constants,我有UIViewController子类。我有一个常数,我想加载它。为此,我使用了一个函数来设置它的默认值。这里有两个init方法,因为我以前使用它们来设置值。然后我发现我不能调用一个常用的方法来设置值。似乎只有init方法可以设置类常量的值。当我创建函数来设置默认值时,我发现有一个无限循环,它从init(nibName,bundle)函数重复调用我的目标函数。我是斯威夫特的新手,不知道自己做错了什么 class ViewController: UIViewController { let
UIViewController
子类。我有一个常数,我想加载它。为此,我使用了一个函数来设置它的默认值。这里有两个init
方法,因为我以前使用它们来设置值。然后我发现我不能调用一个常用的方法来设置值。似乎只有init方法可以设置类常量的值。当我创建函数来设置默认值时,我发现有一个无限循环,它从init(nibName,bundle)函数重复调用我的目标函数。我是斯威夫特的新手,不知道自己做错了什么
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()
}
}
重写方法时,应调用此方法的超级实现
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个位置设置变量示例
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框架中,类有不止一种实例化它们的方法,并且有许多初始化器。示例UIViewController具有init(nibName:String?,bundle:NSBundle?
和init(coder:NSCoder)
我们将如何初始化这个类
您有两个相同的代码。如果您需要更改或修复它,您需要在两个位置执行相同的操作。非常糟糕的架构和代码味道
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)
}
我们能做得更好吗?解决方案看起来很明显-在单独的方法中提取名称初始化。但是我们不能这样做,因为安全规则初始化步骤
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"
}
}
谢谢我没有注意到我没有在每种情况下调用正确的init。当我扩展UIViewController时,是否有一种方法可以为我的子类执行公共初始化工作?我理解您对便利初始化的看法,但我认为在对其他人的实现进行子类化时,我无法做到这一点,因为Xcode和故事板将决定调用哪个初始值设定项。@Brian我已经对我的解决方案添加了更多解释。请看一下它的详细说明。我怀念Objective-C中常见的init方法的使用。如果有一个我们可以表示的方法可以设置公共功能,那就太好了。