Je suis en train de réécrire un cours Objective-C à Swift pour avoir une idée de la langue. En Objective-C, ma classe comprenait la méthode suivante:
- (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"]];
}
Après quelques essais et erreurs avec le compilateur, j'ai réussi à le réécrire comme ceci:
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)
}
Cependant, cela me donne toujours une erreur sur la dernière ligne: «Impossible de trouver une surcharge pour init
qui accepte les arguments fournis.» La signature de méthode de init
est
init(actionName: String, payload: Dictionary<String, NSObject>, timestamp: NSDate)
donc je suppose que le problème est que j'essaie de passer une NSDictionary
au lieu d'un Dictionary<String, NSObject>
. Comment puis-je convertir entre ces deux types pas assez équivalents? Devrais-je simplement utiliser NSDictionary
pour tout le code devant interagir avec d'autres composants Objective-C?
Décodez votre dictionnaire en tant que Dictionary<String, NSObject>
au lieu de NSDictionary
.
let payload = aDecoder.decodeObjectOfClass(NSDictionary.self, forKey: "payload") as! Dictionary<String, NSObject>
Étant donné que vous utilisez Cocoa Touch pour la sérialisation et la désérialisation, elles sont numérotées en tant que NSDictionary
, mais vous pouvez le convertir en un Swift Dictionary<,>
, conformément à WWDC 2014 Intermédiaire Swift et Advanced Swift videos.
Vous pouvez également décoder en tant que NSDictionary
, puis convertir explicitement l'objet de la manière suivante:
self.init(actionName: actionName, payload: payload as! Dictionary<String, NSObject>, timestamp: timestamp)
Fondamentalement, vous jouez ici avec covariance/contravariance.
Etes-vous sûr que c'est la déclaration correcte pour init? L'ordre des arguments est différent de celui que vous appelez dans votre code Objective-C.
Donc, si vous voulez une réimplémentation précise, le dernier appel devrait probablement être self.init(actionName: actionName, timestamp: timestamp, payload: payload)
. Appeler l'initialiseur avec le mauvais ordre d'arguments entraînerait exactement le message d'erreur que vous obtenez.