2017-03-16 68 views
2

返回我有一個應用程序中,我想創建一個基於是否已經有保存到用戶的默認等同對象的對象。如果檢測到對象,我想在類init中檢測到它並提前返回。這就是我要做的:如何從早期一個init在迅速3

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 

} 

有在控制檯一對夫婦的錯誤,自己是不可改變的,等我想知道這是否是一個有效的模式是什麼,或者我應該完全考慮不同的方法。

回答

3

在Swift中(與ObjC不同),init無法返回與自身不同的對象。實現你想要做的事情的一種常見方法是使用類工廠方法(如果不希望其他對象能夠直接調用它,可選地使其爲init)。

例如,沿着這些路線的東西:

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()這樣的東西很清楚地表明有外部影響。

+0

感謝這正是我需要的分析。我仍然遇到的一個麻煩是,即使我將自定義對象保存爲默認值,並且可以_seemingly_加載它,但是在創建對象時,屬性都是默認值。我是否需要採取其他一些措施,如實施NSCoding,或者什麼? – zeeple

+0

這取決於你如何將它寫入用戶默認值。儘管一般情況下如果你的方法需要'NSCoding',那麼如果不這樣做,它就不會工作。我會確保你實際上正在寫你認爲你正在寫的東西,並且你實際上是從你正在閱讀的內容中創造出一種價值。很多'print'語句或斷點在這裏是你的朋友。 –