【问题标题】:index 4 beyond bounds [0 .. 3]' ... Terminating app due to uncaught exception 'NSRangeException'索引 4 超出范围 [0 .. 3]' ... 由于未捕获的异常“NSRangeException”而终止应用程序
【发布时间】:2017-03-17 01:23:50
【问题描述】:

我不确定我在哪里做错了。

let recievedJson = json
let results = recievedJson["results"] as! NSArray
let resultsDic = results[0] as! NSDictionary
let address = resultsDic["address_components"] as? NSArray
let zipcodeDic = address?[0] as! NSDictionary
let cityNameDic = address?[1] as! NSDictionary
let countyDic = address?[2] as! NSDictionary
let stateDic = address?[3] as! NSDictionary
let countryDic = address?[4] as! NSDictionary
let zipcode = zipcodeDic["long_name"] as! String
let cityName = cityNameDic["long_name"] as! String
let countyName = countyDic["long_name"] as! String
let stateName = stateDic["long_name"] as! String
let stateShortName = stateDic["short_name"] as! String
let countryName = countryDic["long_name"] as! String
let countryShortName = countryDic["short_name"] as! String

试图从这个 json 响应中检索数据

http://maps.googleapis.com/maps/api/geocode/json?address=23508&sensor=true

这对我有用,对@Danh 答案的小改动。

let recievedJson: [String: Any] = json as! [String : Any]
        if let results = recievedJson["results"] as? [[String: Any]] {

            if results.count > 0 {
                let resultsDic = results[0]

                if let address = resultsDic["address_components"] as? [[String: Any]] {

                    for dict in address {

                        if let longName = dict["long_name"] as? String,
                            let shortName = dict["short_name"] as? String,
                            let types = dict["types"] as? [String] {

                            if types.contains("postal_code") {

                                print("postal_code: \(longName)")
                            } else if types.contains("locality") {

                                print("city: \(longName)")
                            } else if types.contains("administrative_area_level_2") {

                                print("county: \(longName)")
                            } else if types.contains("administrative_area_level_1") {

                                print("state: \(longName)")
                            } else if types.contains("country") {

                                print("country: \(longName)")
                            }
                        }
                    }
                }
            }
        }

【问题讨论】:

  • 做出这样的假设绝不是一个好主意。防守代码。摆脱所有as! 并使用if let ... as? ...。在尝试访问特定索引之前检查数组计数。
  • 而且由于您使用的是 Swift,请避免使用 NSDictionaryNSArray。使用具有正确类型信息的 Swift 字典和 Swift 数组。
  • @rmaddy 如果我不使用 NSArray/NSDictionary,xcode 会显示错误“对成员 'subscript' 的模糊引用”
  • @Karen 使用新代码编辑您的问题。

标签: arrays json swift swift3


【解决方案1】:

address 数组有 4 个项目(索引从 0 到 3)但您访问的项目的索引是 4,所以您收到此错误。您应该使用Optional Binding - if let 解包值并在下标之前检查数组的count。让我们使用 Swift 类型。代码必须是:

let recievedJson: [String: Any] = json
    if let results = recievedJson["results"] as? [[String: Any]] {

        if results.count > 0 {
            let resultsDic = results[0]

            if let address = resultsDic["address_components"] as? [[String: Any]] {

                // zipcode
                if address.count > 0 {

                    let zipcodeDic = address[0]
                    if let zipcode = zipcodeDic["long_name"] as? String {
                        print("zipcode: \(zipcode)")
                    }
                }

                // cityName
                if address.count > 1 {

                    let cityNameDic = address[1]
                    if let cityName = cityNameDic["long_name"] as? String {
                        print("cityName: \(cityName)")
                    }
                }

                // stateName
                if address.count > 2 {

                    let stateDic = address[2]
                    if let stateName = stateDic["long_name"] as? String {
                        print("stateName: \(stateName)")
                    }
                    if let stateShortName = stateDic["short_name"] as? String {
                        print("stateShortName: \(stateShortName)")
                    }
                }

                // countryDic
                if address.count > 3 {

                    let countryDic = address[3]
                    if let countryName = countryDic["long_name"] as? String {
                        print("countryName: \(countryName)")
                    }
                    if let countryShortName = countryDic["short_name"] as? String {
                        print("countryShortName: \(countryShortName)")
                    }
                }
            }
        }
    }

更新:从 Google Maps API 中提取地址组件

let recievedJson: [String: Any] = json
if let results = recievedJson["results"] as? [[String: Any]] {

    if results.count > 0 {
        let resultsDic = results[0]

        if let address = resultsDic["address_components"] as? [[String: Any]] {

            for dict in address {

                if let longName = dict["long_name"] as? String,
                    let shortName = dict["short_name"] as? String,
                    let types = dict["types"] as? [String] {

                    if types.contains("postal_code") {

                        print("postal_code: \(longName)")
                    } else if types.contains("locality") {

                        print("city: \(longName)")
                    } else if types.contains("administrative_area_level_2") {

                        print("county: \(longName)")
                    } else if types.contains("administrative_area_level_1") {

                        print("state: \(longName)")
                    } else if types.contains("country") {

                        print("country: \(longName)")
                    }
                }
            }
        }
    }
}

【讨论】:

  • 非常感谢您的帮助,但我发现了一些其他问题。见下文,我认为缺少县 json,因此将国家/地区值分配给 stateName.. 我认为您的答案并不完全正确.. 邮政编码:23508 城市名称:诺福克县名称:弗吉尼亚州名称:美国 stateShortName:US
  • 我的意思是在少数情况下,县响应是数组的 2 个元素,有时不是。在代码中,我们还应该在分配值之前与键进行比较。请参阅下面的链接以获取两种不同的响应。 maps.googleapis.com/maps/api/geocode/…maps.googleapis.com/maps/api/geocode/…
  • 是否有国家类型的响应?管理区域..等,应该是一个比较参数。
  • 更新:他们提供了types,所以你可以检查这个值
猜你喜欢
  • 1970-01-01
  • 2015-05-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多