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?
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 tempName
nil
ist, ist entweder der Schlüssel nicht vorhanden oder der entsprechende Wert ist von einem anderen Typ.
Es gab zwei Dinge, die ich tun musste, damit es funktioniert:
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"
}