Swift 为什么可以';是否更改此会话中的实例变量。dataTask()?

Swift 为什么可以';是否更改此会话中的实例变量。dataTask()?,swift,Swift,我试图直接将从URLsession接收到的数据更新到实例变量中。在playgroud中尝试了下面的代码,直到self.cityName=weatherdecoded.name代码似乎工作正常,但是作为实例变量的self.cityName没有更新。结果是nils。希望了解原因,我犯了什么错误。谢谢 import UIKit class WeatherManager { var cityName: String? var conditionID: Int? var temp:

我试图直接将从URLsession接收到的数据更新到实例变量中。在playgroud中尝试了下面的代码,直到
self.cityName=weatherdecoded.name
代码似乎工作正常,但是作为实例变量的
self.cityName
没有更新。结果是
nil
s。希望了解原因,我犯了什么错误。谢谢

import UIKit
class WeatherManager {
    var cityName: String?
    var conditionID: Int?
    var temp: Double?


    func fetchData(cityName: String) {
        let session = URLSession(configuration: .default)
        let urlStr = "https://api.openweathermap.org/data/2.5/weather?units=metric&appid=8da179fa1c83749056ec6a5385cabb04&q=" + cityName.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)!
        print(urlStr)
        let url = URL(string: urlStr)!

        let weatherDataSession = session.dataTask(with: url, completionHandler: getdata(data:response:error:))
        weatherDataSession.resume()
    }

    func getdata(data: Data?, response: URLResponse?, error: Error?) {
        if error != nil {
                print(error!)
                return
            }

            if let safedata = data {
                let decoder = JSONDecoder()
                do {
                   let weatherdecoded = try decoder.decode(Weatherdata.self, from: safedata)

                    self.cityName = weatherdecoded.name
                    self.conditionID = weatherdecoded.weather[0].id
                    self.temp = weatherdecoded.main.temp

                } catch {
                    print(error)
                }
            }
        }
}

struct Weatherdata: Decodable {
    let weather : [Weather]
    let main: Main
    let name: String
}

struct Weather: Decodable {
    let id: Int
    let description: String
}

struct Main: Decodable {
    let temp: Double
}

let weathermanager = WeatherManager()
weathermanager.fetchData(cityName: "beijing")

print(weathermanager.cityName)
print(weathermanager.conditionID)
print(weathermanager.temp)


原因很简单,因为您正在请求实际完成之前打印这些值。您必须使用完成处理程序:

class WeatherManager {
    func fetchObject<T: Decodable>(urlPath: String, onCompletion: @escaping (Result<T, Error>) -> Void) {
        let session = URLSession(configuration: .default)
        let url = URL(string: urlPath)!

        let task = session.dataTask(with: url) { data, _, error in
            if let error = error {
                onCompletion(.failure(error))
                return
            }

            let decoder = JSONDecoder()
            do {
               let decoded = try decoder.decode(T.self, from: data ?? Data())
                onCompletion(.success(decoded))
            } catch {
                onCompletion(.failure(error))
            }
        }

        task.resume()
    }


    func fetchWeather(cityName: String, onCompletion: @escaping (Result<Weatherdata, Error>) -> Void) {
        let urlPath = "https://api.openweathermap.org/data/2.5/weather?units=metric&appid=8da179fa1c83749056ec6a5385cabb04&q=" + cityName.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)!

        fetchObject(urlPath: urlPath, onCompletion: onCompletion)
    }
}

struct Weatherdata: Decodable {
    let weather : [Weather]
    let main: Main
    let name: String
}

struct Weather: Decodable {
    let id: Int
    let description: String
}

struct Main: Decodable {
    let temp: Double
}

let weathermanager = WeatherManager()
weathermanager.fetchWeather(cityName: "beijing") { result in
    switch result {
    case .success(let weatherData):
        print(weatherData.name)
        print(weatherData.weather[0].id)
        print(weatherData.main.temp)
    case .failure(let error):
        print(error)
    }
}
类天气管理器{
func fetchObject(urlPath:String,onCompletion:@escaping(Result)->Void){
let session=URLSession(配置:。默认值)
让url=url(字符串:urlPath)!
让task=session.dataTask(with:url){data,\中出现错误
如果let error=error{
完成(.failure(error))
返回
}
let decoder=JSONDecoder()
做{
let decoded=尝试decoder.decode(T.self,from:data??data())
完成(.success(已解码))
}抓住{
完成(.failure(error))
}
}
task.resume()
}
func fetchWeather(cityName:String,onCompletion:@escaping(Result)->Void){
让urlPath=”https://api.openweathermap.org/data/2.5/weather?units=metric&appid=8da179fa1c83749056ec6a5385cabb04&q=“+cityName.addingPercentEncoding(使用允许的字符:.urlQueryLowed)!
fetchObject(urlPath:urlPath,onCompletion:onCompletion)
}
}
结构Weatherdata:可解码{
让天气:[天气]
让main:main
let name:String
}
结构天气:可解码{
让id:Int
let description:字符串
}
主结构:可解码{
温度:双倍
}
让weathermanager=weathermanager()
weathermanager.fetchWeather(城市名称:“北京”){结果
切换结果{
成功案例(让weatherData):
打印(weatherData.name)
打印(weatherData.weather[0].id)
打印(天气数据主温度)
案例。失败(let错误):
打印(错误)
}
}

URLSession.dataTask
是异步的。从阅读Swift中的异步执行和完成处理程序开始