2017-03-16 9 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をプライベートにします)。例えば、これらの線に沿って何か

を:

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) 
} 

:あなたの現在のAPIに近い

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 
} 

別のアプローチは、このような個別の(おそらくプライベート)指定イニシャライザを作成することですこのアプローチの1つの問題は、それが少し驚くかもしれないということです。 Heroオブジェクトを複数作成した場合、何が起こるはずかは正確には分かりません。 loadOrCreate()のようなものは、外部の影響があることを非常に明確にしています。

+0

これは正確に私が必要とした分析です。私がまだ実行している1つの問題は、カスタムオブジェクトをデフォルトに保存しても、それを遡ってロードすることができますが、オブジェクトが作成されたときのプロパティはすべてデフォルト値です。 NSCodingなどの実装のようないくつかのステップを踏む必要がありますか? – zeeple

+0

これはユーザーのデフォルトにどのように書き込んでいるかによって異なります。一般に、あなたのアプローチが 'NSCoding'を必要としていたとしても、そうしなければ全く機能しません。あなたが書いていると思っていることを実際に書いていることを確かめ、あなたが読んでいるものから実際に価値を創造していることを確認します。たくさんの 'print'ステートメントやブレークポイントがあなたの友人です。 –

関連する問題