web-dev-qa-db-de.com

cast NSString! schnell zu schnüren

Ich habe einen Instanzvariablennamen in String

var name: String

Meine Klasse implementiert das NSCoding-Protokoll. Also für den Namen, den ich hatte

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

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

Ergebnis? Ich bekam einen Laufzeitabsturz während der Einführung mit Decoder. Ich habe init folgendermaßen geändert:

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

und erkannte, dass der Wert temp den richtigen NSString-Wert hält. Ich dachte, die Zeile unten würde das Problem beheben, aber es wird ein Linker-Fehler ausgegeben:

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

die fragen ist, wie man die temp und namen nimmt?

13
Arash

decodeObjectForKey gibt einen optionalen AnyObject? zurück, sodass Sie Ihren Code vor möglichen Nullwerten schützen müssen. Das Verwenden eines Casts zu einem erzwungenen Umwickeln ist nicht sicher.

Ich kann den Fehler nicht reproduzieren (das Problem könnte sich also an einer anderen Stelle in Ihrem Code befinden), aber so würde ich beim Initialisieren der name-Eigenschaft vorgehen:

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

Beachten Sie die Verwendung des optionalen Downcastings as?, das im Gegensatz zu as NSString! immer ein Ergebnis (nil oder einen gültigen Typwert) erzeugt. Dies löst eine Ausnahme aus, wenn der Downcast nicht möglich ist (wenn Sie z. B. eine Zeichenfolge erwarten, aber eine stattdessen).

Mit diesem Code können Sie auch besser debuggen. Wenn tempNamenil ist, ist entweder der Schlüssel nicht vorhanden oder der entsprechende Wert ist von einem anderen Typ.

4
Antonio

Es gab zwei Dinge, die ich tun musste, damit es funktioniert: 

  1. clean Build mit Entfernen des abgeleiteten Datenordners
  2. Aus irgendeinem Grund funktioniert die Überbrückung zwischen NSString und String in dieser Situation nicht. Das Casting sollte also in zwei Schritten erfolgen

    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