Бросьте NSString! Строка в быстрой
У меня есть имя переменной экземпляра в String
var name: String
Мой класс реализует протокол NSCoding. Так что для имени у меня был
func encodeWithCoder(aCoder: NSCoder) {
aCoder.encodeObject(self.name, forKey: kName)
}
required init(coder aDecoder: NSCoder) {
self.name = aDecoder.decodeObjectForKey(kName) as String // CRASH HERE
}
Результат? Во время инициирования с декодером я получал крах во время выполнения. Я изменил init на это:
var temp = aDecoder.decodeObjectForKey(kName) as NSString!
self.name = aDecoder.decodeObjectForKey(kName) as String
и понял, что значение temp имеет правильное значение NSString. поэтому я подумал, что строка ниже собирается исправить это, но она выдает ошибку компоновщика:
self.name = aDecoder.decodeObjectForKey(kName) as NSString!
вопросы: как взять temp и поместить его в имя?
Ответы
Ответ 1
decodeObjectForKey
возвращает необязательный AnyObject?
, поэтому вам нужно защитить свой код от возможных значений nil. Использование броска для принудительной развертки не звучит безопасно.
Я не могу воспроизвести ошибку (так что проблема может быть где-то еще в вашем коде), но именно так я хотел бы при инициализации свойства name
:
var tempName = aDecoder.decodeObjectForKey("name") as? String
if let tempName = tempName {
self.name = tempName
} else {
self.name = "some initial value"
}
Обратите внимание на использование необязательного downcasting as?
, который всегда производит результат (нуль или допустимое значение типа) в отличие от as NSString!
, который запускает исключение, если нисходящее недоступно (например, если вы ожидая строку, но вместо нее вместо int).
Этот код также позволит вам лучше отлаживать - если tempName
есть nil
, то либо ключ не существует, либо соответствующее значение имеет другой тип.
Ответ 2
Мне нужно было сделать две вещи, чтобы заставить ее работать:
- очистить сборку с удалением папки с производными данными
-
По какой-то причине переключение между NSString и String не работает в этой ситуации. поэтому литье должно выполняться в два этапа
if let name = aDecoder.decodeObjectForKey(kName) as? NSString {
self.name = name as String
} else {
assert(false, "ERROR: could not decode")
self.name = "ERROR"
}