2016-09-17 12 views
2

次のコードの2行目と3行目はswift 2.3で動作していましたが、swift 3に更新してからエラーが発生しましたCan not call非関数型の値 'Any ?!'それらの両方のためのエラー:Swift 3で '非機能型の値を呼び出すことはできません'

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

これは、Googleマップの検索からのコールバックです。この方法は、読んでいる

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

誰もが、私はそれを動作させるために変更を行ういる知っているしていますか?

+1

を公開していますとにかくそのコードは恐ろしいです。それをいくつかの行に解凍すると、はるかに読みやすくなります。ほとんどの行が繰り返されるので、ステートメントを分離するのは大したことではありません。 – Paulw11

+0

コード内で 'object(0)'がわかりません。また、コードはSwift 2に変換されていなくても悪い習慣... JSONデータの文字列表現の例を教えてください。 – OOPer

+0

コードは読みにくいかもしれませんが、Swift 2.3で動作し、3ではない場合は理由が必要です。 –

答えて

3

JSONを解析するときスウィフトにかなり悪いです物事のカップルがあります。

  • NSDictionaryまたはNSArrayにキャスト、何の型情報を持っていません。
  • AnyObjectへのキャスティングは非常に不定です。
  • valueForKeyであり、これはキー値符号化方法であり、この場合は必要ではない。
  • オプションmutableleavesは、スウィフトタイプを使用するときは意味がなく、オブジェクトのみを読み取るときには不要です。

すべてのチュートリアルは、プログラミングの習慣が貧弱であることを示唆しています。 ;-)

AnyObjectはスウィフト3にAnyに置き換えられていることを考えてみましょう

JSONは2つだけのコレクション型、arrayサポート - とdictionary - - []で表さ{}で表現します。

JSONを確実に解析するには、JSONを慎重に読んで構造を識別し、コンパイラーにノードのタイプを伝える必要があります。

主な間違いは、キーresultsの値のタイプがの間違ったタイプです。

また、このコードオプションのバインディングを持つすべてのキーが存在するかどうかを確認し、配列が空でないとlocationのための辞書は2つの項目が含まれている場合:

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は包括的な記事にWorking with JSON in Swift

+0

オプションのバインディングに 'lat'と' lng'を含めないのはなぜですか?単に 'count'をチェックするよりも安全かもしれません。 – OOPer

+0

@OOP 'location'が空でない場合は、' lat'と 'lng'として何が含まれていますか? – vadian

+0

次に、サーバーが正常に動作し、有効なJSONを返す場合、他のすべての型チェックは不要ですか? – OOPer

関連する問題