web-dev-qa-db-fra.com

tapez tout? n'a pas de membres inscrits

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.

11
KKG

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!
18
Alexander

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

1
dfri

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])")
    }
0
Reginaldo Costa