type een? heeft geen lidmaatschapsleden

Ik wil adressen ophalen uit het profielwoordenboek, maar ik krijg de foutmelding “type any? has no subscript members”

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

Hoe kan ik het oplossen en het adres krijgen? Heel erg bedankt.


Antwoord 1, autoriteit 100%

Als je je profiel abonneert met "Addresses", krijg je een Any-instantie terug. Uw keuze om Anyte gebruiken om verschillende typen binnen dezelfde array te passen, heeft ertoe geleid dat typeverwijdering is opgetreden. U moet het resultaat terug casten naar het echte type, [[String: Any]], zodat het weet dat de instantie Anyeen Array. Dan kun je het abonneren:

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])
}

Dit is echter erg onhandig, en het is niet erg geschikt om in de eerste plaats woordenboeken te gebruiken.

In een dergelijke situatie, waar je woordenboeken hebt met een vaste set sleutels, zijn structs een meer geschikte keuze. Ze zijn sterk getypeerd, dus je hoeft niet op en neer te casten vanaf Any, ze presteren beter en zijn veel gemakkelijker om mee te werken. Probeer dit:

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!

Antwoord 2, autoriteit 14%

Je zou moeten heroverwegen hoe je hebt gekozen om adressen profilesamen te stellen; zie bijv. Alexander Momchliovs antwoord.


Voor de technische discussie kunt ude Anyleden van profileextraheren waarvan u weet dat ze [String: Any]woordenboeken verpakt in een Anyarray; door opeenvolgende poging tot typeconversie van profile["Addresses"]naar [Any]gevolgd door element voor element (poging tot) conversie naar [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"]
}

of, zonder tussenstap …

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"]
}

Maar dit is slechts een kleine les in pogingen tot getypte conversie (-> niet doen).


Antwoord 3

Ik ben het ermee eens dat als je je ontwerp heroverweegt zoals eerder gesuggereerd. Ter wille van de discussie kun je het volgende doen om te bereiken wat je zoekt.

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

LEAVE A REPLY

Please enter your comment!
Please enter your name here

1 + 2 =

Other episodes