2014-09-20 11 views
12

Mam instancji nazwę zmiennej w Stringobsada NSString! String w szybkim

var name: String 

Moja klasa implementuje protokół NSCoding. Tak więc na imię miałem

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

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

Wynik? Podczas inicjowania z dekoderem otrzymywałem awarię podczas uruchamiania. Zmieniłem init na:

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

i ustalono, że wartość temperatury zawiera prawidłową wartość NSString. tak myślałem linię poniżej zamierza go naprawić, ale to wydaje się błąd linkera:

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

pytań jest, jak zabrać temp i umieścić go pod nazwą?

+0

Spróbuj: 'self.name = aDecoder.decodeObjectForKey (kName) jako AnyObject! as String' –

+0

Dzięki za odpowiedź, ale nadal się zawiesza. – Arash

Odpowiedz

4

decodeObjectForKey zwraca opcjonalny AnyObject?, więc musisz chronić swój kod przed możliwymi wartościami zerowymi. Używanie rzutu do wymuszonego rozpakowania nie brzmi bezpiecznie.

nie jestem w stanie odtworzyć błąd (więc problem może być gdzieś indziej w kodzie), ale jest to w jaki sposób podchodzę podczas inicjalizacji właściwość name:

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

Uwaga korzystanie z opcjonalnego downcasting as?, który zawsze generuje wynik (zero lub poprawną wartość typu) w przeciwieństwie do as NSString!, który uruchamia wyjątek, jeśli downcast nie jest możliwy (na przykład, jeśli oczekujesz ciągu znaków, ale zamiast tego jest to int).

Ten kod również pozwala na lepsze debugowanie - jeśli tempName jest nil, wówczas klucz nie istnieje lub odpowiadająca mu wartość jest innego typu.

+4

Możesz zastąpić swoją logikę if/else wyrażeniem używającym operatora koalesminacji Swift w następujący sposób: 'self.name = tempName ?? "pewna wartość początkowa" ' – jlehr

+0

Tak, dobra rada. Nie używałem tego tylko dla jasności, ale nawet nie wspomniałem :) – Antonio

+0

dzięki za odpowiedź. ale wydaje się, że problem pochodzi z NSString! na ciąg. – Arash

0

Były dwie rzeczy muszę zrobić, aby dostać pracy:

  1. czysty budować z wyjęciem pochodzący folder danych
  2. Z jakiegoś powodu mostków między NSString i ciąg nie działa w tej sytuacji . tak odlewania powinny być wykonywane w dwóch etapach

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

. , ostatnia linia nigdy nie zostanie wywołana, ale czego potrzebowałeś? – HenryRootTwo

+2

assert tylko zatrzymuje wykonywanie w kompilacjach debugowania - jest to ta sama semantyka co wersja C. Zobacz bardzo fajny wpis na blogu o tym, jak zbudowali ten https://developer.apple.com/swift/blog/?id=4 –