J'essaye actuellement de décoder la liste de propriété en utilisant le protocole PropertyListEncoder
et Swift 4 Codable
.
J'ai essayé quelques types de base (Strings, Ints, ..) et tout cela fonctionne très bien, mais je ne suis pas capable de décoder l'URL. J'ai lu plusieurs articles sur ce sujet et je suis sûr que cela devrait fonctionner. Cependant, l'exemple suivant échoue le décodage avec cette erreur:
Expected to decode Dictionary<String, Any> but found a string/data instead.
Je pense que cela fonctionne correctement avec les fichiers .json
et je n'ai trouvé aucune information sur le support différent pour les types codables dans JSONDecoder
et PropertyListDecoder
. Cela pourrait-il être causé par l'incompatibilité de l'analyseur?
J'utilise Xcode 9.1 et Swift 4.0.2.
Échantillon .plist
:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>web</key>
<string>https://link.to</string>
</dict>
</plist>
Exemple de code Swift:
struct Info: Codable {
let web: URL
}
func loadInfo() {
let propertiesDecoder = PropertyListDecoder()
let data = try! Data(contentsOf:
Bundle.main.url(forResource: "web", withExtension: "plist")!)
try! propertiesDecoder.decode(Info.self, from: data)
}
Merci pour toute aide!
3 réponses
Comme vous pouvez dans le XML brut, il est stocké sous forme de chaîne. Les plists AFAIK ne prennent pas en charge les URL. Cela devrait fonctionner si vous changez simplement web
en String.
Si vous devez utiliser la propriété comme URL, je vous suggère d'utiliser une propriété calculée:
var webURL: URL? {
//return your url
}
Comme je peux le voir, la clé web
a une valeur de type String
, nous devons donc conserver un type correspondant
Mais pour obtenir la chaîne en tant que URL
, nous devons ajouter une variable calculée et peut-être pour l'optimiser un peu, nous pouvons rendre la variable paresseuse, c'est-à-dire qu'elle sera calculée une fois quand c'est nécessaire
La jambe de force modifiée ressemblerait à ceci:
struct Info: Codable {
let web: String
lazy var url: URL? = { return URL(string: web) }()
}
Vous pouvez stocker des URL dans des listes de propriétés et utiliser l'implémentation décodable par défaut.
Basé sur l'implémentation du URL(string: relative, relativeTo: base) lors du décodage.
Par exemple:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<array>
<dict>
<key>apiHost</key>
<dict>
<key>relative</key>
<string>https://example.com/api/v0</string>
</dict>
<key>otherKey</key>
<string>SomeValue</string>
</dict>
</array>
</plist>
Ce Plist décodera en utilisant ce qui suit:
struct PlistItem: Codable {
let apiHost: URL
let otherKey: String
}
guard let filePath = Bundle.main.url(forResource: "Data", withExtension: "plist") else { return }
do {
let data = try Data(contentsOf: filePath)
let decoder = PropertyListDecoder()
let values = try decoder.decode([PlistItem].self, data)
}
catch { }
Questions connexes
De nouvelles questions
ios
iOS est le système d'exploitation mobile fonctionnant sur Apple iPhone, iPod touch et iPad. Utilisez cette balise [ios] pour les questions liées à la programmation sur la plate-forme iOS. Utilisez les balises associées [objective-c] et [swift] pour les problèmes spécifiques à ces langages de programmation.