将 JSON 数据显示到 swift 中的出口

Displaying JSON data to an outlet in swift

我对编码非常陌生,并且正在尝试一次一个步骤地学习东西。我搜索了一堆,发现了一些很棒的想法,但没有任何东西能回答我希望学到的东西。

我创建了一些代码,可以从单个网络 URL 中提取 JSON 天气数据。它只共享一个位置的天气数据,不请求该信息。

我可以打印 JSON 数据中的信息! (这是一个巨大的进步)。下一步是在我的应用程序和 phone 上显示来自 JSON 数据的信息。我在 table 视图中找到了很多关于执行此操作的帖子,但无法使它适用于我的应用程序,主要是因为其中许多要求您搜索位置以提取数据(这不是适用于我的情况)。

我想从 JSON 数据中提取一条信息并将其显示在我的屏幕上。

我在故事板中创建了一个标签并将其连接到我的视图控制器。

我还有 weather.swift 调用 JSON 数据。

我遇到的问题 运行 是我遇到的错误 "Value of type '[Weather]' has no member 'name'"。在我看来 controller.swift 代码行 "locationOutlet.text = observationsData.name".

这是我的视图控制器中的代码:

导入 UIKit

class ViewController: UIViewController {

@IBOutlet weak var locationOutlet: UILabel!

var observationsData = [Weather]()


override func viewDidLoad() {
    super.viewDidLoad()

   /* Weather.observations(withLocation: ",") { (results:[Weather]) in
        for result in results {
                print("\(result)\n\n")
        }
       */

    }

// Do any additional setup after loading the view, typically from a nib.

    func loadweatherData (location:String) {

        Weather.observations(withLocation: ",") { (results:[Weather]?) in
                if let weatherData = results {
                    self.observationsData = weatherData
            }

            //let weatherObject = observationsData[IndexPath.row]

    }

    func displayweatherData (location:String) {

        locationOutlet.text = observationsData.name

    }
    //locationOutlet?.text = observationsData.name

}

}

这里是 weather.swift 中调用 JSON 数据的代码。

import Foundation

struct Weather {
    let name:String
    let air_temp:Double
    let wind_spd_kt:Double
    let swell_height:Double


    enum SerializationError:Error {
        case missing(String)
        case invalid(String, Any)
    }

init(json:[String:Any]) throws {
    guard let name = json["name"] as? String else{throw SerializationError.missing("Name is missing")}

    guard let air_temp = json["air_temp"] as? Double else{throw SerializationError.missing("Air temp is missing")}

    guard let wind_spd_kt = json["wind_spd_kt"] as? Double else{throw SerializationError.missing("Wind speed is missing")}

    guard let swell_height = json["swell_height"] as? Double else{throw SerializationError.missing("Swell hight is missing")}

    self.name = name
    self.air_temp = air_temp
    self.wind_spd_kt = wind_spd_kt
    self.swell_height = swell_height
}

static let basePath = "http://www.bom.gov.au/fwo/IDN60701/IDN60701.94937.json"

static func observations (withLocation location:String, completion: @escaping ([Weather]) -> ()) {

    let url = basePath //+ location
    let request = URLRequest(url: URL(string: url)!)

    let task = URLSession.shared.dataTask(with: request) { (data:Data?, response:URLResponse?, error:Error?) in

    var observationsArray:[Weather] = []

    if let data = data {

    do {
        if let json = try JSONSerialization.jsonObject(with: data, options: []) as? [String:Any] {
            if let currentObservations = json["observations"] as? [String:Any] {
                if let currentData = currentObservations["data"] as? [[String:Any]] {
                    for dataPoint in currentData {
                        if let weatherObject = try? Weather(json: dataPoint) {
                            observationsArray.append(weatherObject)
                                        }
                                    }
                                }
                            }
                        }
    }catch{
        print(error.localizedDescription)
    }

    completion(observationsArray)

    }
}

task.resume()
}

}

很明显,我正在学习并尝试做一些可能比我想象的更难的事情。任何关于如何让我的标签显示数据的帮助都会很棒。感谢您的宝贵时间!

您正在尝试访问数组 [Weather].name 相反,您可能想要访问 Weather.name

尝试访问数组中的一个 Weather 对象

然后你所要做的就是获取第一个索引的天气对象并在标签中显示它的属性。

Weather.observations(withLocation: ",") { (results) in
    if let firstIndexWeatherData = results.first {
        //As API calls are usually on background thread and Apple requires Main Thread to update the UI so set your weatherData name to label on main thread like this.
        DispatchQueue.main.async {
            self.locationOutlet.text = firstIndexWeatherData.name
        }
    }
}