当init()初始化成员变量和引用时,放置super.init()的位置" self"

时间:2016-10-05 07:34:19

标签: ios swift swift2 swift3

我正在学习Swift,现在我有了这段代码:

import SpriteKit
import GameplayKit

class Player: GKEntity {

var spriteComponent : SpriteComponent

init(imageName: String) {
    super.init() // gives error: self.spriteComponent not initialized at super.init call
    let texture = SKTexture(imageNamed:  imageName)
    spriteComponent = SpriteComponent(entity: self, texture: texture, size:  texture.size())

    // super.init() Placing it here gives error on line above: "self used before super.init() call"
    addComponent(spriteComponent)
}

required init?(coder aDecoder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
}

}

我已经看到了关于此问题的其他问题,但我无法想象我必须在SpriteComponent中创建一个虚拟初始值设定项(零args)并调用它:

var spriteComponent = SpriteComponent()

为了在引用" self"

之前调用super.init()

任何人都能解释为什么我要做这种愚蠢的踢踏舞吗?肯定有一个更好的方法来做对吗?斯威夫特不能*&%& /(%右?

4 个答案:

答案 0 :(得分:1)

必须在创建对象之前初始化所有非可选属性。使您的财产成为可选项。

答案 1 :(得分:1)

spriteComponent是一个非可选的var。因此,必须在调用super.init之前初始化它(解释第一个提到的错误)。

以后通过调用super.init无法解决此问题,因为SpriteComponent的构造函数需要对self的引用,该引用仅在调用super.init后才可用。 (解释第二个错误)

作为一种解决方案,您可以使spriteComponent成为一个未包装的可选项:

var spriteComponent : SpriteComponent!

这指示编译器允许spriteComponent不被初始化,并且让你有责任在稍后的时间自己做。

答案 2 :(得分:1)

这种“踢踏舞”有一个原因。 在swift中,类初始化是两阶段初始化:

阶段#1 - 所有存储的属性都由定义它们的类给出一些初始值(nil也很好)

阶段#2 - 现在每个类可以更改初始值并使用self

为什么?安全主要 - 在第2阶段了解所有属性都有一些值。

因此,在您的代码中,您可能不需要空的虚拟初始值设定项,但将精灵组件转换为可选项可能很方便:

class Player: GKEntity{
var spriteComponent : SpriteComponent? = nil  // optional

init(imageName: String)
{
    super.init() // now OK

    let texture = SKTexture(imageNamed:  imageName)
    spriteComponent = SpriteComponent(entity: self, texture: texture, size:  texture.size())!
    addComponent(spriteComponent!)  // unwrap here
}
required init?(coder aDecoder: NSCoder)
{
    fatalError("init(coder:) has not been implemented")
}

}

答案 3 :(得分:1)

您必须初始化子类中声明的所有非可选属性,然后才能调用super.init()

所以你有两种方法可以解决这些问题:

  1. 将属性类型更改为可选(SpriteComponent?SpriteComponent!)。
  2. 在声明它之前初始化每个属性,或在调用super.init之前初始化每个属性
  3. 在你的情况下,第一个选项更适合。

    您可以在此处找到有关Swift两阶段初始化的更多信息: https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/Initialization.html

    本教程也可能有所帮助:(向子类添加属性段落): https://www.raywenderlich.com/121603/swift-tutorial-initialization-part-2