Je souhaite obtenir les adresses du dictionnaire de profils, mais l'erreur "type quelconque? N'a pas de membre en indice"
var address:[[String : Any]] = [["Address": "someLocation", "City": "ABC","Zip" : 123],["Address": "someLocation", "City": "DEF","Zip" : 456]]
var profile:[String : Any] = ["Name": "Mir", "Age": 10, "Addresses": address]
profile["Addresses"][0] <-----------------type any? has no subscript members
Comment puis-je résoudre ce problème et obtenir l'adresse? Merci beaucoup.
Lorsque vous souscrivez un profil avec "Addresses"
, vous obtenez une instance Any
. Votre choix d'utiliser Any
pour adapter différents types dans le même tableau a entraîné l'effacement du type. Vous devrez convertir le résultat en son type réel, [[String: Any]]
, afin qu'il sache que l'instance Any
représente une Array
. Ensuite, vous pourrez l'indiquer:
func f() {
let address: [[String : Any]] = [["Address": "someLocation", "City": "ABC","Zip" : 123],["Address": "someLocation", "City": "DEF","Zip" : 456]]
let profile: [String : Any] = ["Name": "Mir", "Age": 10, "Addresses": address]
guard let addresses = profile["Addresses"] as? [[String: Any]] else {
// Either profile["Addresses"] is nil, or it's not a [[String: Any]]
// Handle error here
return
}
print(addresses[0])
}
C’est cependant très maladroit et il n’est pas très approprié d’utiliser des dictionnaires en premier lieu.
Dans une telle situation, où vous avez des dictionnaires avec un ensemble fixe de clés, les structures sont un choix plus approprié. Ils sont fortement typés, vous n'avez donc pas besoin de monter et descendre de Any
, ils ont de meilleures performances et ils sont beaucoup plus faciles à utiliser. Essaye ça:
struct Address {
let address: String
let city: String
let Zip: Int
}
struct Profile {
let name: String
let age: Int
let addresses: [Address]
}
let addresses = [
Address(
address: "someLocation"
city: "ABC"
Zip: 123
),
Address(
address: "someLocation"
city: "DEF"
Zip: 456
),
]
let profile = Profile(name: "Mir", age: 10, addresses: addresses)
print(profile.addresses[0]) //much cleaner/easier!
Vous devriez repenser à la façon dont vous avez choisi de construire adress
et profile
; voir par exemple Réponse de Alexander Momchliov .
Pour la discussion technique, vous pourriez extraire les membres Any
de profile
que vous savez contenir les dictionnaires [String: Any]
encapsulés dans un tableau Any
; par tentative de conversion séquentielle de type de profile["Addresses"]
en [Any]
suivie de conversion élément par élément (tentative) en [String: Any]
:
if let adressDictsWrapped = profile["Addresses"] as? [Any] {
let adressDicts = adressDictsWrapped.flatMap{ $0 as? [String: Any] }
print(adressDicts[0]) // ["Zip": 123, "City": "ABC", "Address": "someLocation"]
print(adressDicts[1]) // ["Zip": 456, "City": "DEF", "Address": "someLocation"]
}
ou, sans étape intermédiaire ...
if let adressDicts = profile["Addresses"] as? [[String: Any]] {
print(adressDicts[0]) // ["Zip": 123, "City": "ABC", "Address": "someLocation"]
print(adressDicts[1]) // ["Zip": 456, "City": "DEF", "Address": "someLocation"]
}
Mais ceci n’est qu’une petite leçon de tentative de conversion typée (-> ne le faites pas).
Je conviens que si vous repensez votre conception comme suggéré précédemment. Pour des raisons de discussion, vous pouvez effectuer les opérations suivantes pour atteindre vos objectifs.
var address:[[String : Any]] = [["Address": "someLocation", "City": "ABC","Zip" : 123],["Address": "someLocation", "City": "DEF","Zip" : 456]]
var profile:[String : Any] = ["Name": "Mir", "Age": 10, "Addresses": address]
if let allAddresses = profile["Addresses"] as? [[String:Any]] {
print("This are all the address \(allAddresses[0])")
}