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 Any
te 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 Any
een 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 adress
en profile
samen te stellen; zie bijv. Alexander Momchliovs antwoord.
Voor de technische discussie kunt ude Any
leden van profile
extraheren waarvan u weet dat ze [String: Any]
woordenboeken verpakt in een Any
array; 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])")
}