J'essaie de créer une extension de dictionnaire où Dictionary est du type <String, AnyObject>.
Regardait dans de nombreux endroits et essayait différentes approches, mais aucune ne semblait fonctionner. C'était l'un d'entre eux:
extension Dictionary where <String, AnyObject>{
var jsonString:String {
return ""
}
}
ne autre méthode qui n'a pas fonctionné pour une raison quelconque:
extension Dictionary where Key:Hashable, Value:AnyObject {
var jsonString:String {
do {
let stringData = try NSJSONSerialization.dataWithJSONObject(self, options: NSJSONWritingOptions.PrettyPrinted)
if let string = String(data: stringData, encoding: NSUTF8StringEncoding){
return string
}
}catch _ {
}
return ""
}
}
Got: le type d'argument 'Dictionary' n'est pas conforme au type attendu de 'AnyObject'
A partir de la 3.1, nous pouvons faire des extensions concrètes, c'est-à-dire:
extension Dictionary where Key == String {}
Nous ne pouvons pas conformer des types de béton avec des génériques de béton, c'est-à-dire:
extension Dictionary where Key == String
Cependant, comme Dictionary est conforme à la séquence et que nous pouvons conformer les types de protocoles avec des génériques concrets, nous pourrions faire:
extension Sequence where Iterator.Element == (key: String, value: AnyObject) {
func doStuff() {...
Sinon, nous pouvons contraindre notre clé à un protocole dont la chaîne se conforme à ceci:
extension Dictionary where Key: StringLiteralConvertible, Value: AnyObject {
var jsonString: String {
return ""
}
}
Selon votre réponse mise à jour. La sérialisation Json a besoin d'un objet, Swift Les dictionnaires sont des structures. Vous devez convertir en NSDictionary
Vous devez spécifier Key
pour vous conformer à NSObject
pour convertir correctement en NSDictionary
.
Petite remarque: les dictionnaires tapent déjà constrain
Key
pour êtreHashable
, donc votre contrainte d'origine n'ajoutait rien.
extension Dictionary where Key: NSObject, Value:AnyObject {
var jsonString:String {
do {
let stringData = try NSJSONSerialization.dataWithJSONObject(self as NSDictionary, options: NSJSONWritingOptions.PrettyPrinted)
if let string = String(data: stringData, encoding: NSUTF8StringEncoding){
return string
}
}catch _ {
}
return ""
}
}
Notez que les dictionnaires doivent être conformes à ce type pour accéder à l'extension.
let dict = ["k" : "v"]
Deviendra le type [String : String]
, vous devez donc être explicite en déclarant:
let dict: [NSObject : AnyObject] = ["k" : "v"]
Approche Swift
extension Dictionary where Key: ExpressibleByStringLiteral, Value: AnyObject
Comme StringLiteralConvertible est désormais obsolète et remplacé par ExpressibleByStringLiteral
Ajout à la réponse fournie par @Logan, pour ceux qui cherchent à ajouter des propriétés personnalisées à la chaîne de caractères Dictionary
, cela est également possible (cherchait à le faire lorsque je suis tombé sur ce SO question):
extension Dictionary where Key: StringLiteralConvertible {
var somePropertyThatIsAColor:UIColor? {
get {
return self["someKey"] as? UIColor
}
set {
// Have to cast as optional Value
self["someKey"] = (newValue as? Value)
}
}
Mise à jour pour Swift
Voici mon exemple utilisant ExpressibleByStringLiteral
pour Key
et Any
pour Value
.
extension Dictionary where Key: StringLiteralConvertible, Value: Any {
var jsonString: String? {
if let dict = (self as AnyObject) as? Dictionary<String, AnyObject> {
do {
let data = try JSONSerialization.data(withJSONObject: dict, options: JSONSerialization.WritingOptions(rawValue: UInt.allZeros))
if let string = String(data: data, encoding: String.Encoding.utf8) {
return string
}
} catch {
print(error)
}
}
return nil
}
}
puis je l'utilise comme ceci:
let dict: Dictionary<String, AnyObject> = [...]
let jsonString = dict.jsonString
Vous pouvez vous convertir en AnyObject ou NSObject, les deux fonctionnent, puis vous décompressez en tant que dictionnaire ou tout autre type spécifique.
Ainsi, Dictionary
est:
public struct Dictionary<Key : Hashable, Value> : CollectionType, DictionaryLiteralConvertible {..}
Que diriez-vous d'une extension de protocole? :RÉ
extension CollectionType where Self: DictionaryLiteralConvertible, Self.Key == String, Self.Value == AnyObject, Generator.Element == (Self.Key, Self.Value) {
...
}
Je n'ai pas réussi à faire fonctionner l'une des solutions proposées dans Swift 3, mais en profitant du pont entre Dictionary et NSDictionary, je pouvais faire ce travail:
extension NSDictionary {
var jsonString:String {
do {
let stringData = try JSONSerialization.data(withJSONObject: self, options: .prettyPrinted)
if let string = String(data: stringData, encoding: .utf8) {
return string
}
}catch _ {
}
return ""
}
}
Toute personne utilisant [String:Any]
au lieu de Dictionary
peut utiliser l'extension ci-dessous
extension Dictionary where Key == String, Value == Any {
mutating func append(anotherDict:[String:Any]) {
for (key, value) in anotherDict {
self.updateValue(value, forKey: key)
}
}
}