2014-06-07 13 views
19

Przepisuję klasę Objective-C w języku Swift, aby uzyskać wyczucie języka. W Objective-C moja klasa zawiera następującą metodę:Jak przekonwertować NSDictionary na Swift Dictionary <String, NSObject>?

- (id) initWithCoder:(NSCoder *)aDecoder 
{ 
    return [self initWithActionName:[aDecoder decodeObjectOfClass:[NSString class] forKey:@"actionName"] 
          payload:[aDecoder decodeObjectOfClass:[NSDictionary class] forKey:@"payload"] 
          timestamp:[aDecoder decodeObjectOfClass:[NSDate class] forKey:@"timestamp"]]; 
} 

Po kilku prób i błędów z kompilatora, udało mi się przerobić go tak:

convenience init(aDecoder: NSCoder) { 
    let actionName = aDecoder.decodeObjectOfClass(NSString.self, forKey: "actionName") as NSString 
    let payload = aDecoder.decodeObjectOfClass(NSDictionary.self, forKey: "payload") as NSDictionary 
    let timestamp = aDecoder.decodeObjectOfClass(NSDate.self, forKey: "timestamp") as NSDate 
    self.init(actionName: actionName, payload: payload, timestamp: timestamp) 
} 

to jednak wciąż daje mi błąd w ostatnim wierszu: „nie znaleźliśmy przeciążenie dla init który akceptuje dostarczonych argumentów” metoda podpis init jest

init(actionName: String, payload: Dictionary<String, NSObject>, timestamp: NSDate) 

więc zakładam, że problem polega na tym, że próbuję przekazać NSDictionary zamiast Dictionary<String, NSObject>. Jak mogę przekonwertować te dwa typy nie całkiem równoważne? Czy powinienem używać tylko NSDictionary dla całego kodu, który musi współdziałać z innymi komponentami Objective-C?

Odpowiedz

14

Dekodowanie słownika jako Dictionary<String, NSObject> zamiast NSDictionary.

let payload = aDecoder.decodeObjectOfClass(NSDictionary.self, forKey: "payload") as! Dictionary<String, NSObject> 

Ponieważ używasz Cocoa Touch do serializacji i Cofnięcie są szeregowane jako NSDictionary, ale można oddać go do Swift Dictionary<,>, jak na WWDC 2014 Pośrednik Swift i zaawansowane Swift filmów.

Można również dekodować jak NSDictionary a następnie jawnie rzutować obiektu tak:

self.init(actionName: actionName, payload: payload as! Dictionary<String, NSObject>, timestamp: timestamp) 

Zasadniczo grasz tutaj z kowariancji/kontrawariancji.

1

Czy jesteś pewien, że jest to poprawna deklaracja dla init? Kolejność argumentów różni się od tej, do której wywołujesz swój kod Celu-C.

Tak więc, jeśli chcesz dokładną reimplementację, ostatnie połączenie powinno prawdopodobnie być self.init(actionName: actionName, timestamp: timestamp, payload: payload). Wywołanie inicjalizatora z nieprawidłową kolejnością argumentów spowoduje dokładnie komunikat o błędzie, który otrzymujesz.

+0

Przepraszamy za zamieszanie - odkąd przerobiłem zajęcia, postanowiłem zmodyfikować interfejs API w tym samym czasie. Kolejność argumentów metody Swift jest poprawna, więc to nie problem. Zmieniłem to pytanie, aby zmienić kolejność argumentów w wersji ObjC, więc nie ma zamieszania. – bdesham

Powiązane problemy