Ios 从API(JSON格式)提取数据不需要';t在函数调用之外保存数据

Ios 从API(JSON格式)提取数据不需要';t在函数调用之外保存数据,ios,json,swift,api,swift3,Ios,Json,Swift,Api,Swift3,我试图从JSON格式的API中获取给定时间段内的温度数组。我能够通过一个完成处理程序检索数组,但是我不能将它保存到函数调用之外的另一个变量(使用完成处理程序的变量)。这是我的密码。请查看评论区 class WeatherGetter { func getWeather(_ zip: String, startdate: String, enddate: String, completion: @escaping (([[Double]]) -> Void)) {

我试图从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)

    }

这不是一个错误,当您的
控制器
被加载时,数组仍然是空的,因为您的
getWeather
仍在做它的事情(意味着访问api,解码json),当它完成
回调
时,将有
数据
返回到您的控制器

例如,如果您使用的是tableView,则在将数据分配给
weatherData

或者,您可以在声明
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:)

问题是,API返回数据需要一些时间,当数据返回时,将调用“Completion Listener”,并将其放入“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)

}

更新用户界面是什么意思?我很抱歉。我是iOS编程新手。更新UI意味着如果您想在视图中设置数据。如果您使用数据显示在某些标签上,则设置文本,但如果您将数据设置为Tablview,则调用:yourTableView.reloadData()哦,我明白了。这很有帮助。我基本上只是尝试获取完成处理程序返回的数组,并将其保存到一个全局变量中,稍后我可以在代码的其他部分中使用它。您建议我如何实现这一点?它已保存在weatherData对象中。只是需要一些时间。当您转到任何其他控制器并访问该对象时。我将获得您的数据。我可以打印此声明中的数组,但仍然无法将其分配给全局变量。我很抱歉。我是新来的。