2017-03-17 109 views
1

我不知道我在哪里做错了。索引4超越界限[0..3]'...终止应用程序由于未捕获的异常'NSRangeException'

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)") 
          } 
         } 
        } 
       } 
      } 
     } 
+0

这是不是一个好主意做出这样的假设提取的地址组成部分。代码防守。摆脱所有的'as!'并使用'如果让...作为? ...'。在尝试访问特定索引之前检查数组数量。 – rmaddy

+0

而且由于您使用Swift,请避免使用'NSDictionary'和'NSArray'。使用适当类型信息的Swift字典和Swift数组。 – rmaddy

+0

@rmaddy如果我不使用NSArray/NSDictionary,xcode显示错误“模糊引用成员下标'” – Karen

回答

0

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

更新:从谷歌地图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)") 
        } 
       } 
      } 
     } 
    } 
} 
+0

我非常感谢您的帮助,但我看到了其他一些问题。见下面我想县JSON缺少分配给Statename的这样的国家价值。我认为你的回答是不完全正确..邮编:23508 的cityName:诺福克 countyName:弗吉尼亚 Statename的:美国 stateShortName:美国 – Karen

+0

我是什么意思在少数情况下有县响应为阵列的2个元素,有些时候没有。在代码中,我们还应该在分配值之前将其与密钥进行比较。请参阅下面的链接,了解两种不同的回应http://maps.googleapis.com/maps/api/geocode/json?address=23508&sensor=true http://maps.googleapis.com/maps/api/geocode/json?address=20171&sensor=true – Karen

+0

还有类型对于这个答复是否是国家?管理区域等等,这应该是一个比较参数。 – Karen

相关问题