从API(JSON格式)中提取数据不会在函数调用之外保存数据

时间:2017-06-20 19:02:51

标签: ios json swift api swift3

我试图从JSON格式的API获取给定时间段内的温度数组。我能够通过完成处理程序检索数组,但我无法将其保存到函数调用之外的另一个变量(使用完成处理程序的变量)。这是我的代码。请参阅评论区域。

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)

    }

2 个答案:

答案 0 :(得分:0)

这不是一个错误,当你的controller加载数组仍然是空的,因为你的getWeather仍在做它的事情(意思是访问api,解码json)当它完成时callbackdata返回您的控制器。

例如,如果您使用的是tableView,则在将数据分配给reloadData()后,您将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逻辑放入`struct :)

答案 1 :(得分:0)

问题是当数据返回"完成侦听器"时,API需要一些时间来返回数据。被调用,它进入" getWeather"方法实现,它打印数组的数据。但是当调用外部打印方法时,API还没有返回数据。所以它显示空数组。如果您将尝试打印数据表格" weatherData"对象在一段时间后会起作用。

我建议你的最好方法是使用" getWeather"中的数据更新你的用户界面。像这样的方法实现:

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)

}