错误:“无法调用Swift 3上的非函数类型的值”

时间:2021-12-19 18:03:57

The second and third lines of the following code were working on swift 2.3 and since I updated to swift 3, I've been getting the error Cannot call value of non-function type 'Any?!' for both of them:

以下代码的第二行和第三行都在处理swift 2.3,自从我更新到swift 3以来,我一直得到错误,不能调用非函数类型的值'Any?!”“对他们两人来说:

let dic = try JSONSerialization.jsonObject(with: data!, options: JSONSerialization.ReadingOptions.mutableLeaves) as! NSDictionary                    

let lat = ((((dic["results"] as AnyObject).value(forKey: "geometry") as AnyObject).value(forKey: "location") as AnyObject).value(forKey: "lat") as AnyObject).object(0) as! Double
let lon = ((((dic["results"] as AnyObject).value(forKey: "geometry") as AnyObject).value(forKey: "location") as AnyObject).value(forKey: "lng") as AnyObject).object(0) as! Double

self.delegate.locateWithLongitude(lon, andLatitude: lat, andTitle: self.searchResults[(indexPath as NSIndexPath).row])

This is the callback from a google maps search.

这是谷歌映射搜索的回调。

The JSON that the method is reading is this:

方法读取的JSON是:

{
   "results" : [
      {
         "address_components" : [
            {
               "long_name" : "São Paulo",
               "short_name" : "São Paulo",
               "types" : [ "locality", "political" ]
            },
            {
               "long_name" : "São Paulo",
               "short_name" : "São Paulo",
               "types" : [ "administrative_area_level_2", "political" ]
            },
            {
               "long_name" : "State of São Paulo",
               "short_name" : "SP",
               "types" : [ "administrative_area_level_1", "political" ]
            },
            {
               "long_name" : "Brazil",
               "short_name" : "BR",
               "types" : [ "country", "political" ]
            }
         ],
         "formatted_address" : "São Paulo, State of São Paulo, Brazil",
         "geometry" : {
            "bounds" : {
               "northeast" : {
                  "lat" : -23.3566039,
                  "lng" : -46.36508449999999
               },
               "southwest" : {
                  "lat" : -24.0082209,
                  "lng" : -46.825514
               }
            },
            "location" : {
               "lat" : -23.5505199,
               "lng" : -46.63330939999999
            },
            "location_type" : "APPROXIMATE",
            "viewport" : {
               "northeast" : {
                  "lat" : -23.3566039,
                  "lng" : -46.36508449999999
               },
               "southwest" : {
                  "lat" : -24.0082209,
                  "lng" : -46.825514
               }
            }
         },
         "partial_match" : true,
         "place_id" : "ChIJ0WGkg4FEzpQRrlsz_whLqZs",
         "types" : [ "locality", "political" ]
      }
   ],
   "status" : "OK"
}

Does anyone knows what I have do change to make it work?

有人知道我做了什么改变来让它工作吗?

1 个解决方案

#1


3  

There are a couple of things which are pretty bad in Swift when parsing JSON:

在对JSON进行解析时,Swift有一些非常糟糕的地方:

  • casting to NSDictionary or NSArray, which have no type information.
  • 转换到NSDictionary或NSArray,它们没有类型信息。
  • casting to AnyObject which is very unspecified.
  • 对任何对象进行强制转换,这是非常不明确的。
  • valueForKey which is a key-value coding method and not necessary in this case.
  • valueForKey是一种键值编码方法,在本例中没有必要。
  • The option mutableleaves which is meaningless when using Swift types and never needed when the objects are only read.
  • 选项mutableleaves在使用快速类型时毫无意义,在对象仅被读取时也不需要它。

Sue all tutorials which suggest that poorly programming habit. ;-)

苏所有的教程,建议不良的编程习惯。:-)

Consider that AnyObject has been replaced with Any in Swift 3.

考虑一下,在Swift 3中,AnyObject已经被Any替换。

JSON supports only two collection types, array – represented by [] – and dictionary – represented by {}.

JSON只支持两种集合类型,数组-由[]表示,字典-由{}表示。

To parse JSON reliably you have to read the JSON carefully to identify the structure and tell the compiler the types of the nodes.

要可靠地解析JSON,必须仔细阅读JSON,以识别结构并告诉编译器节点的类型。

Your main mistake is the wrong type of the value for key results which is an array.

您的主要错误是键结果(即数组)的值类型错误。

This code checks for the existence of all keys with optional bindings and also if the array is not empty and the dictionary for location contains 2 items:

此代码检查是否存在具有可选绑定的所有键,并且如果数组不是空的,并且位置字典包含两个项:

if let jsonObject = try JSONSerialization.jsonObject(with: data!, options: []) as? [String:Any],
  let results = jsonObject["results"] as? [[String:Any]], !results.isEmpty,
  let geometry = results[0]["geometry"] as? [String:Any],
  let location = geometry["location"] as? [String:Double],
  let lat = location["lat"], let lng = location["lng"] {

  print("lat: \(lat) - lng: \(lng)")
} 

Apple has published a comprehensive article Working with JSON in Swift

苹果在Swift发布了一篇关于JSON的综合文章

#1


3  

There are a couple of things which are pretty bad in Swift when parsing JSON:

在对JSON进行解析时,Swift有一些非常糟糕的地方:

  • casting to NSDictionary or NSArray, which have no type information.
  • 转换到NSDictionary或NSArray,它们没有类型信息。
  • casting to AnyObject which is very unspecified.
  • 对任何对象进行强制转换,这是非常不明确的。
  • valueForKey which is a key-value coding method and not necessary in this case.
  • valueForKey是一种键值编码方法,在本例中没有必要。
  • The option mutableleaves which is meaningless when using Swift types and never needed when the objects are only read.
  • 选项mutableleaves在使用快速类型时毫无意义,在对象仅被读取时也不需要它。

Sue all tutorials which suggest that poorly programming habit. ;-)

苏所有的教程,建议不良的编程习惯。:-)

Consider that AnyObject has been replaced with Any in Swift 3.

考虑一下,在Swift 3中,AnyObject已经被Any替换。

JSON supports only two collection types, array – represented by [] – and dictionary – represented by {}.

JSON只支持两种集合类型,数组-由[]表示,字典-由{}表示。

To parse JSON reliably you have to read the JSON carefully to identify the structure and tell the compiler the types of the nodes.

要可靠地解析JSON,必须仔细阅读JSON,以识别结构并告诉编译器节点的类型。

Your main mistake is the wrong type of the value for key results which is an array.

您的主要错误是键结果(即数组)的值类型错误。

This code checks for the existence of all keys with optional bindings and also if the array is not empty and the dictionary for location contains 2 items:

此代码检查是否存在具有可选绑定的所有键,并且如果数组不是空的,并且位置字典包含两个项:

if let jsonObject = try JSONSerialization.jsonObject(with: data!, options: []) as? [String:Any],
  let results = jsonObject["results"] as? [[String:Any]], !results.isEmpty,
  let geometry = results[0]["geometry"] as? [String:Any],
  let location = geometry["location"] as? [String:Double],
  let lat = location["lat"], let lng = location["lng"] {

  print("lat: \(lat) - lng: \(lng)")
} 

Apple has published a comprehensive article Working with JSON in Swift

苹果在Swift发布了一篇关于JSON的综合文章