Swift:根据网络请求初始化模型数据[weatherApp]

我正在使用Swift中的weatherApp,它从openweather.org请求一些数据,但是在将数据转换为模型数据时遇到了问题

数据模型类

import Foundation

class CurrentWeather {
    let temperature: Int?
    let tempMin: Int?
    let tempMax: Int?
    let location: String?

    struct WeatherKeys {
        static let temperature = "temp"
        static let tempMin = "temp_min"
        static let tempMax = "temp_max"
        static let location = "name"
    }

    init(weatherDictionary: [String: Any]) {
        temperature = weatherDictionary[WeatherKeys.temperature] as? Int
        tempMax = weatherDictionary[WeatherKeys.tempMax] as? Int
        tempMin = weatherDictionary[WeatherKeys.tempMin] as? Int
        location = weatherDictionary[WeatherKeys.location] as? String

    }
}

网络请求类别

import Foundation
import Alamofire

class WeatherService {

    let APIKey = "c70ff4cc260c1075bbfb6849caa1ad29"
    let weatherBaseURL = "http://api.openweathermap.org/data/2.5/weather?"

    func getcurrentWeather(latitude: Double,longitude: Double,completion: @escaping (CurrentWeather?) -> Void) {
        if let weatherURL = URL(string: "\(weatherBaseURL)lat=\(latitude)&lon=\(longitude)&appid=\(APIKey)") {
            Alamofire.request(weatherURL).responseJSON(completionHandler: { (response) in
                if let jsonDictionary = response.result.value as? [String: Any] {
                    if let currentWeatherDictionary = jsonDictionary["main"] as? [String: Any] {

                        //Print to show the data from the URL

                         print(currentWeatherDictionary)

                        //Initialize model data with currentWeatherDictionary(NOT WORKING)
                        let currentWeather = CurrentWeather(weatherDictionary: currentWeatherDictionary)
                        completion(currentWeather)
                    } else {
                        completion(nil)
                    }
                }

            })
        }
    }

}

当前WeatherDictionary的结果是 [“温度”:297.73,“温度最小”:294.15,“温度最大”:301.48,“湿度”:33,“压力”:1017]

我想使用数据模型将其值分配给它在viewController中的适当标签 目前,它没有显示我的temperatureLabel值,只是“-”


    let coordinate: (lat: Double,long: Double) = (37.8267,-122.4233)
    var weatherService = WeatherService()

    override func viewDidLoad() {
        super.viewDidLoad()
        weatherService.getcurrentWeather(latitude: coordinate.lat,longitude: coordinate.long) { (currentWeather) in
            if let currentWeather = currentWeather {
                DispatchQueue.main.async {
                    if let temperature = currentWeather.temperature {
                        self.temperatureLabel.text = "\(temperature)"
                    } else {
                        self.temperatureLabel.text = "-"
                    }
                }
            }
        }        
    }
markrolon 回答:Swift:根据网络请求初始化模型数据[weatherApp]

温度为零的原因是由于将 currentWeatherDictionary 中的 Double 类型转换为 Int 类型您的模型。

您可以通过将 Int 类型更改为 Double 类型来修改模型:

    class CurrentWeather {
        let temperature: Double?
        let tempMin: Double?
        let tempMax: Double?
        let location: String?

        struct WeatherKeys {
            static let temperature = "temp"
            static let tempMin = "temp_min"
            static let tempMax = "temp_max"
            static let location = "name"
        }

        init(weatherDictionary: [String: Any]) {
            temperature = weatherDictionary[WeatherKeys.temperature] as? Double
            tempMax = weatherDictionary[WeatherKeys.tempMax] as? Double
            tempMin = weatherDictionary[WeatherKeys.tempMin] as? Double
            location = weatherDictionary[WeatherKeys.location] as? String

        }
    }

您可以使用以下代码在操场上对其进行测试:

class CurrentWeather {
    let temperature: Double?
    let tempMin: Double?
    let tempMax: Double?
    let location: String?

    struct WeatherKeys {
        static let temperature = "temp"
        static let tempMin = "temp_min"
        static let tempMax = "temp_max"
        static let location = "name"
    }

    init(weatherDictionary: [String: Any]) {
        temperature = weatherDictionary[WeatherKeys.temperature] as? Double
        tempMax = weatherDictionary[WeatherKeys.tempMax] as? Double
        tempMin = weatherDictionary[WeatherKeys.tempMin] as? Double
        location = weatherDictionary[WeatherKeys.location] as? String

    }
}

 let currentWeather = CurrentWeather(weatherDictionary: ["temp": 297.73,"temp_min": 294.15,"temp_max": 301.48,"humidity": 33,"pressure": 1017])


if let temperature = currentWeather.temperature {
         print(temperature)
     } else {
         print("-")
     }

注意:您模型中位置键的字符串不在您提供的currentWeatherDictionary中。

["temp": 297.73,"pressure": 1017]

因此位置将为

建议使用协议 CodingKey 和协议可解码来映射不同的密钥名称。查看本文“ Codable cheat sheet”进行演示

,

openweathermap的所有温度数据均为Double,而不是Int

location字典中没有键main

使用Decodable解码数据要容易得多

struct WeatherData : Decodable {
    let main : CurrentWeather
}

struct CurrentWeather : Decodable {
    let temp,tempMin,tempMax : Double
    let pressure,humidity : Int
}

class WeatherService {

    let APIKey = "c70ff4cc260c1075bbfb6849caa1ad29"
    let weatherBaseURL = "http://api.openweathermap.org/data/2.5/weather?"

    func getCurrentWeather(latitude: Double,longitude: Double,completion: @escaping (CurrentWeather?) -> Void) {
        if let weatherURL = URL(string: "\(weatherBaseURL)lat=\(latitude)&lon=\(longitude)&appid=\(APIKey)") {
            Alamofire.request(weatherURL).responseData(completionHandler: { (response) in
                switch response.result {
                case .success(let data):
                  let decoder = JSONDecoder()
                  decoder.keyDecodingStrategy = .convertFromSnakeCase
                  let result = try decoder.decode(WeatherData.self,from: data!)
                  completion(result.main)

                case .failure(let error): 
                  print(error)
                  completion(nil)
                }
            })
        }
    }
}
本文链接:https://www.f2er.com/3120919.html

大家都在问