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

    }

1 answer

  • answered 2018-08-15 23:53 terrafirma9

    In your MainViewController code, you have the following line:

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

    Is this inside a method, like viewDidLoad? If so, then weatherData is not a property of MainViewController, and is not accessible by a subclass. You have to define it as a property outside of any function scope (e.g. at the top of the file, right after the opening brackets):

    var weatherData = ...
    

    Then call it as such:

    do {
        weatherData = ...