【问题标题】:How to get nested JSON data in Swift 4如何在 Swift 4 中获取嵌套的 JSON 数据
【发布时间】:2018-08-13 16:36:56
【问题描述】:

我在 Swift 4 中为 iOS 制作了一个天气应用程序,我使用 OpenWeatherMap API 将 JSON 数据解析到应用程序,我已经让大部分应用程序正常工作,用户输入城市,天气是显示。我有当前的温度、当前的风速、当前的湿度,我正在尝试让当前的描述正常工作,但我无法显示它。

我想让 MainLabel 显示当前天气描述,但我无法让它工作。代码顶部是来自 API 密钥的 JSON 数据,描述位于 Weather 部分。我尝试过 MainLabel.Weather?.Description,但它会打印出整个描述、ID、Main 和 Icon 值。我将不胜感激。谢谢你

以下是我用来解码来自 OpenWeatherMap API 的 JSON 数据的结构:

JSON 结构如下:

import UIKit


//Below is the JSON data from the OpenWeatherMap API


struct Coordinate : Decodable {
    let lat, lon : Double?
}

struct Weather : Decodable {
    var id : Int?
    var main, myDescription, icon : String?

    enum CodingKeys : String, CodingKey {
        case id = "id"
        case main = "main"
        case icon = "icon"
        case myDescription = "description"
    }
}

struct Sys : Decodable {
    let type, id : Int?
    let sunrise, sunset : Date?
    let message : Double?
    let country : String?
}

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

struct Wind : Decodable {
    let speed : Double?
    let deg : Int?
}

struct MyWeather : Decodable {
    let coord : Coordinate?
    let cod, visibility, id : Int?
    let name : String?
    let base : String?
    let weather : [Weather]?
    let sys : Sys?
    let main : Main?
    let wind : Wind?
    let dt : Date?
}

查看下面的控制器:

class ViewController: UIViewController {



    @IBOutlet weak var HumidityLabel: UILabel!
    @IBOutlet weak var MainLabel: UILabel!
    @IBOutlet weak var WindLabel: UILabel!
    @IBOutlet weak var TempLabel: UILabel!
    @IBOutlet weak var LocationLabel: UILabel!
    //
    @IBOutlet weak var userValue: UITextField!

    //Assigning Labels




    override func viewDidLoad() {
        super.viewDidLoad()

            }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }




    @IBAction func GoButton(_ sender: Any) {

        let text: String = userValue.text!

        guard let APIUrl = URL(string: "https://api.openweathermap.org/data/2.5/weather?q=" + text +  "&appid=e7b2054dc37b1f464d912c00dd309595&units=Metric") else { return }
        //API KEY

        URLSession.shared.dataTask(with: APIUrl) { data, response, error in
            guard let data = data else { return }

            let decoder = JSONDecoder()
            //Decoder

            do {
                let weatherData = try decoder.decode(MyWeather.self, from: data)

                if (self.MainLabel != nil)
                {
                    if let gmain = weatherData.weather?.description {
                        print(gmain)
                        DispatchQueue.main.async {
                            self.MainLabel.text! = String (describing: gmain)
                        }
                    }
                }

                if (self.LocationLabel != nil)
                {
                    if let gmain = weatherData.name {
                        print(gmain)
                        DispatchQueue.main.async {
                            self.LocationLabel.text! = "Current Weather in: " + String (gmain)
                        }
                    }
                }


                if (self.HumidityLabel != nil)
                {
                    if let ghumidity = weatherData.main?.humidity
                    {
                        print(ghumidity, "THIS IS HUMIDITY")
                        DispatchQueue.main.async {
                            self.HumidityLabel.text! = String (ghumidity)
                        }
                    }
                }

                if (self.WindLabel != nil)
                {
                    if let gspeed = weatherData.wind?.speed {
                        print(gspeed, "THIS IS THE SPEED")
                        DispatchQueue.main.async {
                            self.WindLabel.text! = String(gspeed) + " mph"
                        }
                    }
                }

                if (self.TempLabel != nil)
                {
                    if let ggtemp = weatherData.main?.temp {
                        print(ggtemp, "THIS IS THE TEMP")
                        DispatchQueue.main.async {
                            self.TempLabel.text! = String (ggtemp) + " c"
                        }
                    }
                }


            } catch {
                print(error.localizedDescription)
            }
            }.resume()

    }

}

【问题讨论】:

  • 我在您的 GoButton 代码中的任何地方都看不到“描述”。你说它不起作用是什么意思?也不清楚你为什么在这里使用String (describing:),或者根本不使用String(...)。查看这段代码,我认为它只是self.HumidityLabel.text = ghumidity(不是!,而不是String)。请注意命名;变量应该有一个前导小写,而不是大写(即 APIUrl 应该是 apiURL 而 MainLabel 应该是 mainLabel;这在 Cocoa 中可能非常重要)
  • weatherData.weather?.description 替换为weatherData.weather?.first?. myDescription 或从weatherData.weather 天气数组中查找合适的天气

标签: ios swift xcode api openweathermap


【解决方案1】:

停下来想想以下几行:

let weatherData = try decoder.decode(MyWeather.self, from: data)
if let gmain = weatherData.weather?.description {

如果weatherData 是一个MyWeather 实例,那么它的weather 是一个[Weather],因为这就是MyWeather 的声明方式:

struct MyWeather : Decodable {
    // ...
    let weather : [Weather]?
    // ...
}

[Weather] 不是天气。它是一个数组(天气)。所以你要的是 arraydescription。而这正是你得到的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-20
    • 2018-08-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多