19

我想从个人资料字典中获取地址,但出现错误“输入任何?没有下标成员”

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

我怎样才能修复它并获取地址?非常感谢。

4

3 回答 3

29

当您使用 下标配置文件时"Addresses",您将获得一个Any实例。您选择使用Any以适应同一数组中的各种类型已导致发生类型擦除。您需要将结果转换回其真实类型,[[String: Any]]以便它知道该Any实例表示一个Array. 然后你就可以给它下标:

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

虽然这非常笨拙,而且首先使用字典并不是一个非常合适的情况。

在这种情况下,您的字典具有一组固定的键,结构是更合适的选择。它们是强类型的,因此您不必从 向上和向下转换Any,它们具有更好的性能,并且更易于使用。尝试这个:

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!
于 2016-08-15T14:43:19.487 回答
4

您应该重新考虑如何选择构建adressprofile;参见例如Alexander Momchliov 的回答


对于技术讨论,您可以提取您知道的Any成员profile以包含包含在数组[String: Any]中的字典;Any通过顺序尝试类型转换为profile["Addresses"][Any]然后逐个元素(尝试)转换为[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"]
}

或者,没有中间步骤......

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

但这只是尝试类型转换的一个小教训(-> 不要这样做)。

于 2016-08-15T14:51:32.153 回答
0

我同意,如果您按照前面的建议重新考虑您的设计。为了讨论起见,您可以执行以下操作来实现您所寻求的。

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])")
    }
于 2016-08-15T15:19:23.850 回答