2017-06-20 25 views
-1

我想從JSON格式的API中獲取給定時間段內的溫度數組。我能夠通過完成處理程序檢索數組,但我無法將其保存到函數調用之外的另一個變量(使用完成處理程序的變量)。這是我的代碼。請參閱評論區域。從API(JSON格式)中提取數據不會將函數調用以外的數據保存到

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 = "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!) 
        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.append(tempF) 
          winds.append(windspeed) 
         } 
        } 
        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() 
    } 
} 


I am calling this method from my view controller class. Here is the code. 

    override func viewDidLoad() { 
     super.viewDidLoad() 

     let weather = WeatherGetter() 
     weather.getWeather("13323", startdate: "2016-10-01", enddate: "2017-04-30") { (weatherhandler: [[Double]]) in 
      //It prints out the correct array here 
      print(weatherhandler[0]) 
      weatherData = weatherhandler[0] 
     } 
     //Here it prints out an empty array 
     print(weatherData) 

    } 

回答

0

的問題是,API需要一些時間來恢復數據,當數據返回「完成監聽器」之稱,並它進入「getWeather」方法實現中,在那裏它打印數組的數據。但是,當您的外部打印方法被調用時,API尚未返回數據。所以它顯示空陣列。如果您嘗試在某個時間後打印數據表單「weatherData」對象,它將起作用。

我可以建議你,最好的辦法是更新這樣的「的GetWeather」方法實現內部與數據的UI:

override func viewDidLoad() { 
    super.viewDidLoad() 

    let weather = WeatherGetter() 
    weather.getWeather("13323", startdate: "2016-10-01", enddate: "2017-04-30") { (weatherhandler: [[Double]]) in 
     //It prints out the correct array here 
     print(weatherhandler[0]) 
     weatherData = weatherhandler[0] 

     // Update your UI here. 

    } 
    //Here it prints out an empty array 
    print(weatherData) 

} 
+0

更新你的用戶界面是什麼意思?對不起。我是iOS編程新手。 –

+0

更新UI意味着您是否想要將數據設置爲您的視圖。如果您使用的數據顯示在一些標籤上,然後設置文本,但如果您將數據設置爲Tablview,然後調用: yourTableView.reloadData() –

+0

哦,我明白了。這有很大幫助。我基本上只是試圖獲取已完成處理程序返回的數組,並將其保存到一個全局變量,我可以稍後在我的代碼的其他部分中使用它。你如何建議我實現這一目標? –

0

這是不是一個錯誤,當你的controller得到加載陣列仍然是空的,因爲你的getWeather還在做它的事(指訪問API,解碼JSON)當它完成了callback將有data返回到您的控制器。

例如,如果你使用的是的tableView,你將有reloadData()刷新UI,分配數據weatherData

後,或者你可以放置一個property Observer,你宣佈你weatherData財產。

var weatherData:[Double]? = nil { 
    didSet { 
     guard let data = weatherData else { return } 
     // now you could do soemthing with the data, to populate your UI 
    } 
} 

現在數據被分配到wheaterData後,didSet將被調用。

希望幫助,並且還您jsonParsing邏輯放到一個`結構:)

+0

我可以打印此聲明中的數組,但仍無法將其指定到一個全局變量。對不起。我是新來的。 –

相關問題