2017-03-16 1 views
2

J'ai une application dans laquelle je voudrais créer un objet basé sur s'il y a déjà un objet équivalent sauvegardé aux valeurs par défaut de l'utilisateur. Je voudrais détecter cela dans la classe init et revenir tôt, si un objet est détecté. Voilà ce que je suis en train de faire:Comment retourner rapidement à partir d'un init dans swift 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 

} 

Il y a des erreurs de couple dans la console, l'auto est immuable, etc. Ce que je veux savoir si cela est un motif valable ou si je devrais prendre un tout une approche différente.

Répondre

3

Dans Swift (contrairement à ObjC), init ne peut pas retourner un objet différent de lui-même. Une manière courante de réaliser ce que vous essayez de faire ici est d'utiliser une méthode de fabrication de classe (en rendant éventuellement init privé si vous ne voulez pas que d'autres objets puissent l'appeler directement).

Par exemple, quelque chose le long de ces lignes:

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 
} 

Une autre approche qui est plus proche de votre API actuelle est de créer un séparé (éventuellement privé) désigné initialiseur comme ceci:

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

Le Un problème avec cette approche est que cela peut être un peu surprenant. Ce n'est pas très clair ce qui est supposé se produire si vous créez plusieurs objets Hero. quelque chose comme loadOrCreate() rend très clair qu'il existe des influences externes.

+0

merci c'est exactement l'analyse dont j'avais besoin. Un problème que je rencontre encore est que même si je sauvegarde l'objet personnalisé par défaut et que je peux le charger de nouveau, les propriétés sont toutes les valeurs par défaut lorsque l'objet a été créé. Ai-je besoin de prendre une autre étape comme NSCoding de l'outil, ou quelque chose? – zeeple

+0

Cela dépend de la façon dont vous l'écrivez aux valeurs par défaut de l'utilisateur. Bien que généralement, si votre approche nécessite 'NSCoding', alors cela ne fonctionnerait pas du tout sans le faire. Je m'assurerais que vous écrivez réellement ce que vous pensez que vous écrivez, et que vous créez réellement une valeur de ce que vous lisez. Beaucoup de déclarations 'print' ou de points d'arrêt sont vos amis ici. –