2017-06-20 67 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

我可以打印此声明中的数组,但仍无法将其指定到一个全局变量。对不起。我是新来的。 –