2017-06-16 7 views
-2

私はスイフト3で閉鎖から配列を抽出しようとしています。 WeatherGetterクラスにJSONパーサーがあり、viewcontroller.swiftにファイルを読み込んだときにweather_data配列をいくつかの外部変数に割り当てる方法を呼び出していますか?すぐに閉鎖外のデータにアクセスすることができません

class WeatherGetter { 

    func getWeather(_ zip: String, startdate: String, enddate: String, completion: @escaping (([[Double]]) -> Void)) { 
     // This is a pretty simple networking task, so the shared session will do. 
     let session = URLSession.shared 

     let string = "Insert API address" 

     let url = URL(string: string) 
     var weatherRequestURL = URLRequest(url:url! as URL) 
     weatherRequestURL.httpMethod = "GET" 


     // The data task retrieves the data. 
     let dataTask = session.dataTask(with: weatherRequestURL) { 
      (data, response, error) -> Void in 
      if let error = error { 
       // Case 1: Error 
       // We got some kind of error while trying to get data from the server. 
       print("Error:\n\(error)") 
      } 
      else { 
       // Case 2: Success 
       // We got a response from the server! 
       do { 
        var temps = [Double]() 
        var winds = [Double]() 
        let weather = try JSON(data: data!) 
        //print(weather) 
        let conditions1 = weather["data"] 
        let conditions2 = conditions1["weather"] 
        let count = conditions2.count 
        for i in 0...count-1 { 
         let conditions3 = conditions2[i] 
         let conditions4 = conditions3["hourly"] 
         let count2 = conditions4.count 
         for j in 0...count2-1 { 
          let conditions5 = conditions4[j] 
          let tempF = conditions5["tempF"].doubleValue 
          let windspeed = conditions5["windspeedKmph"].doubleValue 
          //temps.updateValue(tempF, forKey: "\(date)//\(j)") 
          temps.append(tempF) 
          winds.append(windspeed) 
         } 
        } 
        //print(temps) 
        //print(winds) 
        completion([temps, winds]) 

       } 
       catch let jsonError as NSError { 
        // An error occurred while trying to convert the data into a Swift dictionary. 
        print("JSON error description: \(jsonError.description)") 
       } 
      } 
     } 

     // The data task is set up...launch it! 

     dataTask.resume() 
    } 


} 

override func viewDidLoad() { 
    super.viewDidLoad() 

    let weather = WeatherGetter() 

    weather.getWeather("13323", startdate: "2016-10-01", enddate: "2017-04-30"){(weather_data) -> Void in 
     print(weather_data[1]) 
    } 

     //Do your stuff with isResponse variable. 
    } 
+0

なぜあなたの 'getWeather()'メソッドは何も返さないのですか?結局のところ、「取得」と呼ばれています。 – NRitH

答えて

0

あなたは、このようなクラスのプロパティに割り当てることができます。

var weatherData: [[Double]]() 

override func viewDidLoad() { 
    super.viewDidLoad() 

    let weather = WeatherGetter() 

    weather.getWeather("13323", startdate: "2016-10-01", enddate: "2017-04-30"){(weather_data) -> Void in 
     self.weatherData = weather_data 
     // reload or display data 
    } 
} 

あなたがネットワーク要求は、いくつかの時間がかかることを覚えておく必要があるので、あなたが知っていればあなたがreloadDataのようなものを呼ぶような理由ですあなたは応答を受けました。

たとえば、ネットワーク応答に応答するのに100ミリ秒かかります。データが応答するまでに、viewDidLoadのすべてのコードは完全に終了する可能性が非常に高いでしょう。受信したデータに応答する必要があります。悪い携帯信号がある場合は、時間がかかることがあります。

これは、コールバック/クロージャを使用する理由です。

getWeather内のコードは、私のために複数のエラーを示していると私はそれを実行させません。操作は

UPDATEを完了したとき、彼らが呼び出されます。

天気予報APIからの応答を得るには、コードをわずかに変更し、コメントを外すことができました。主な問題は、JSONデータを特定の型にキャストしていないことです。

// The data task retrieves the data. 
    let dataTask = session.dataTask(with: weatherRequestURL) { 
     (data, response, error) -> Void in 

     guard error == nil, let data = data else { 
      print("ERROR") 
      return 
     } 

     // Case 2: Success 
     // We got a response from the server! 
     do { 
      var temps = [Double]() 
      var winds = [Double]() 
      if let weather = try JSONSerialization.jsonObject(with: data, options: .allowFragments) as? [String:AnyObject] { 

       if let conditions1 = weather["data"] as? [String:AnyObject] { 
        print(conditions1) 
       } 

      } 
     } catch let jsonError { 
      // An error occurred while trying to convert the data into a Swift dictionary. 
      print("JSON error description: \(jsonError)") 
     } 

    } 

    dataTask.resume() 

上記のコードで、型をキャストしている間に値をアンラッピングするオプションを参照してください。これは、コード全体で行う必要があり、途中で各ステップで正しいデータを取得することを確認します。残念ながら、APIレスポンスはあまりにも大きすぎてここではできません。

Unwrapping JSON Swift

Swift Closures

iOS Networking with Swift - これは私が非常にお勧めの無料のコースです。これは私がiOSネットワークを学んだ方法です。

+0

ありがとうございました。私は初心者でコールバック/クロージャに関する知識はほとんどありません。コールバックを実装するにはどうすればよいですか?私はまだgetWeather関数から配列を取得していません –

+0

getWeather関数内で何をしているかを完全にチェックしていないので、マシン上で実行してチェックします。おそらくあまりにも多くここで閉鎖を説明するにはあまりにも多く、私は共有することができるいくつかのリソース/リンクがあります。最初にコード内で起こっていることを見てみましょう – Scriptable

+0

上記の私の答えを更新し、 – Scriptable

0

@Scriptableに記載されているように、応答が非同期であるため、応答が処理されるまでに時間がかかります。できることはOperationQueue.main.addOperationを追加して、現在のプロセスをメインキューに割り当てます。これにより、ネットワーク応答の処理が優先されます。この部分にreloadDataを入れることもできます。

var weatherData: [Double]() 

override func viewDidLoad() { 
super.viewDidLoad() 

    let weather = WeatherGetter() 

    OperationQueue.main.addOperation { 
     weather.getWeather("13323", startdate: "2016-10-01", enddate: "2017-04-30"){(weather_data) -> Void in 
     print(weather_data[1]) 
     // reloadData() 
     } 
    } 
} 
関連する問題