首页 > 解决方案 > I am trying to call a function from my main ViewController and use it to load JSON data in my Second ViewController

问题描述

I am making a weather app for iOS, and I am trying to call a variable from my main ViewController, to be used in my second ViewController, I am using API data from OpenWeatherMap to display weather data, this works fine on the Main ViewController, and I want it displayed on the second one, as an 'Advanced details' section, that will display the max/min temp, and air pressure etc. (things people don't care about).

I have made an instance of my Main ViewController 'var myCustomViewController: ViewController = ViewController (nibName: nil, bundle: nil)' which works fine, and I am able to call labels, variables, TextBoxes etc from the Main Viewcontroller, but I cannot call the variable 'weatherData', which is the decoder for my JSON data.

In my second View Controller, I want to say 'if let gmain = (myCustomViewController.weatherData.main.tempmax' for example, to get the maximum temperature, but it does not recognise 'weatherData'. I'm very stuck on this and would appreciate any help. Thank you.

Structs in my Main ViewController below:

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?
}

Main ViewController code below:

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?.first?.main) { //using .first because Weather is stored in an array
                print(gmain)
                DispatchQueue.main.async {
                    self.MainLabel.text! = String (gmain)
                }
            }

        }


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

Second ViewController code below:

    var myCustomViewController: ViewController = ViewController (nibName: nil, bundle: nil) //Inheriting from other viewController

            if (self.descriptionLabel != nil)
            {
                if let gmain = (myCustomViewController.weatherData { //NOT RECOGNISING weatherData <<<<<
                    print(gmain)
                    DispatchQueue.main.async {
                        self.descriptionLabel.text! = String (gmain)
                    }
                }
            }

    }

标签: iosjsonswiftxcodeuiviewcontroller

解决方案


在您的 MainViewController 代码中,您有以下行:

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

这是在一个方法里面,比如viewDidLoad?如果是这样,则weatherData不是 MainViewController 的属性,并且不能被子类访问。您必须将其定义为任何函数范围之外的属性(例如,在文件顶部,就在左括号之后):

var weatherData = ...

然后这样称呼它:

do {
    weatherData = ...

推荐阅读