2014-06-07 23 views
19

Sto riscrivendo una classe Objective-C in Swift per avere un'idea della lingua. In Objective-C mia classe incluso il seguente metodo:Come si converte un NSDictionary in un dizionario Swift <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"]]; 
} 

Dopo alcuni tentativi ed errori con il compilatore, sono riuscito a riscrivere in questo modo:

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) 
} 

Tuttavia, questo mi dà ancora un errore sull'ultima riga: “Impossibile trovare un sovraccarico per init che accetta gli argomenti forniti” la firma di metodo di init è

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

quindi presumo il problema è che sto provando a passare uno NSDictionary invece di uno Dictionary<String, NSObject>. Come posso convertire tra questi due tipi non del tutto equivalenti? Dovrei semplicemente usare NSDictionary per tutto il codice che deve interagire con altri componenti Objective-C?

risposta

14

Decodifica il dizionario come Dictionary<String, NSObject> anziché NSDictionary.

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

Dal momento che si sta utilizzando Cocoa Touch per serializzare e deserializzare, sono serializzati come NSDictionary, ma si può lanciare in uno Swift Dictionary<,>, come da WWDC 2014 Intermediario Swift e avanzata Swift video.

Si può anche decodificare come NSDictionary e poi gettato in modo esplicito l'oggetto in questo modo:

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

In sostanza, si sta giocando qui con covarianza/controvarianza.

1

Sei sicuro che sia la dichiarazione corretta per init? L'ordine degli argomenti è diverso da quello che stai chiamando nel tuo codice Objective-C.

Quindi, se si desidera una reimplementazione precisa, l'ultima chiamata dovrebbe essere probabilmente self.init(actionName: actionName, timestamp: timestamp, payload: payload). Chiamando l'inizializzatore con l'ordine errato degli argomenti si otterrebbe esattamente il messaggio di errore che si ottiene.

+0

Scusate per la confusione, poiché stavo riscrivendo la classe, ho deciso di modificare l'API contemporaneamente. L'ordine degli argomenti del metodo Swift è corretto, quindi non è questo il problema. Ho modificato la domanda per cambiare anche l'ordine degli argomenti nella versione ObjC, quindi non c'è confusione. – bdesham

Problemi correlati