如何在swift 3中从init早期返回

时间:2017-03-16 16:29:03

标签: swift init

我有一个应用程序,其中我想基于是否已经将等效对象保存到用户默认值来创建对象。如果检测到对象,我想在类init中检测到这一点并提前返回。这就是我想要做的事情:

init() {

    /* There are two possibilities when creating a hero:
     1. The hero is brand new and needs to be built from scratch
     2. The hero is loaded from defaults  */

    // Check to see if there is existing game data:

    if defaultExistsForGameData() {
        // This means there is a hero to load and no need to create a new one
        self = extractHeroFromDefaults() // This just loads from UserDefaults
        print("Loading hero from defaults with name of: \(hero.heroName).")

        return self
    }

    // These actions are for creating a brand new hero
    let size = CGSize(width: 32, height: 32)
    let heroTexture = SKTexture(imageNamed: "hero2.ico")
    super.init(texture: heroTexture, color: .clear, size: size)

    self.isUserInteractionEnabled = true
    self.name = "hero"

    self.zPosition = 50

}

控制台中有几个错误,self是不可变的等等。我想知道这是一个有效的模式,还是我应该采取完全不同的方法。

1 个答案:

答案 0 :(得分:3)

在Swift中(与ObjC不同),init无法返回与自身不同的对象。您实现此处尝试的常用方法是使用类工厂方法(如果您不希望其他对象能够直接调用它,则可选择将init设为私有)。< / p>

例如,这些内容如下:

class func loadOrCreate() -> Hero {
    if defaultExistsForGameData() {
        // This means there is a hero to load and no need to create a new one
        print("Loading hero from defaults with name of: \(hero.heroName).")
        return extractHeroFromDefaults() // This just loads from UserDefaults
    } else {
        return Hero()
    }
}

private init() {
    let size = CGSize(width: 32, height: 32)
    let heroTexture = SKTexture(imageNamed: "hero2.ico")
    super.init(texture: heroTexture, color: .clear, size: size)

    self.isUserInteractionEnabled = true
    self.name = "hero"

    self.zPosition = 50
}

更接近当前API的另一种方法是创建一个单独的(可能是私有的)指定的初始化程序,如下所示:

private init(name: String, zPosition: Int) {
    let size = CGSize(width: 32, height: 32)
    let heroTexture = SKTexture(imageNamed: "hero2.ico")
    super.init(texture: heroTexture, color: .clear, size: size)

    self.isUserInteractionEnabled = true
    self.name = name
    self.zPosition = zPosition
}

public convenience init() {
    let name: String
    let zPosition: Int
    if defaultExistsForGameData() {
        name = defaultName() // Read it out of user defaults
        zPosition = defaultZPosition
    } else {
        name = "hero"
        zPosition = 50
    }
    self.init(name: name, zPosition: zPosition)
}

这种方法的一个问题是它可能有点令人惊讶。如果您创建多个Hero对象,那么应该发生的事情并不清楚。像loadOrCreate()这样的东西非常清楚地表明存在外部影响。