web-dev-qa-db-fra.com

jette NSString! corder en rapide

J'ai un nom de variable d'instance dans String

var name: String

Ma classe implémente le protocole NSCoding. Donc, pour le nom que j'avais

func encodeWithCoder(aCoder: NSCoder) {
    aCoder.encodeObject(self.name, forKey: kName)
}

required init(coder aDecoder: NSCoder) {
    self.name = aDecoder.decodeObjectForKey(kName) as String  // CRASH HERE
}

Résultat? Je commençais à avoir un crash lors de l’initiation au décodeur. J'ai changé init en ceci:

var temp = aDecoder.decodeObjectForKey(kName) as NSString!
self.name = aDecoder.decodeObjectForKey(kName) as String

et réalisé que la valeur temp maintient la bonne valeur NSString. alors j'ai pensé que la ligne ci-dessous va résoudre ce problème, mais il génère une erreur de l'éditeur de liens:

self.name = aDecoder.decodeObjectForKey(kName) as NSString!

la question est de savoir comment prendre le temp et le mettre en nom?

13
Arash

decodeObjectForKey renvoie un AnyObject? facultatif. Vous devez donc protéger votre code contre les éventuelles valeurs nil. Utiliser un casting pour un forcé déballé ne semble pas sans danger.

Je ne parviens pas à reproduire l'erreur (le problème pourrait donc se trouver ailleurs dans votre code), mais voici comment je procéderais lors de l'initialisation de la propriété name:

    var tempName = aDecoder.decodeObjectForKey("name") as? String
    if let tempName = tempName {
        self.name = tempName
    } else {
        self.name = "some initial value"
    }

Notez l'utilisation de l'option as? optionnelle en downcast, qui produit toujours un résultat (nil ou une valeur de type valide) par opposition à as NSString!, qui déclenche une exception si l'abaissement n'est pas possible int à la place).

Ce code vous permettrait également d'améliorer le débogage - si tempName est nil, la clé n'existe pas ou la valeur correspondante est d'un type différent.

4
Antonio

Il y avait deux choses que je devais faire pour que cela fonctionne: 

  1. construction propre avec suppression du dossier de données dérivé
  2. Pour une raison quelconque, le pontage entre NSString et String ne fonctionne pas dans cette situation. donc le casting devrait être fait en deux étapes

    if let name = aDecoder.decodeObjectForKey(kName) as? NSString {
        self.name = name as String
    } else {
        assert(false, "ERROR: could not decode")
        self.name = "ERROR"
    }
    
0
Arash