iOS Dev. Lesson 6

Agenda

  • Finish weather data fetching
  • Expanding weather app with Tab Bar Controller
  • Understanding and using Tab Bar Controller
  • Combining Tab Bar with Navigation Controller
  • Tab Bar x Navigation x Table View Controller

Weather Data Fetching So Far

Step 1: Creating the user interface

Step 2: Connect the IBOutlets

@IBOutlet weak var weatherIcon: UIImageView!
@IBOutlet weak var temperatureLabel: UILabel!
@IBOutlet weak var windLabel: UILabel!
@IBOutlet weak var dateLabel: UILabel!
@IBOutlet weak var todayLabel: UILabel!

Step 3: Inspect the JSON structure

Step 4: Defining the Weather Decodable struct

struct Weather: Decodable {
    var date = ""
    var temperature = ""
    var humidity = ""
    var windSpeed = ""
    var today = ""
    var statusCode = ""
}

Step 5: Defining the fetchWeather function

func fetchWeather() {
    guard let url = URL(string: "https://dev.makzan.net/weather.json") else {
        return
    }
    
    URLSession.shared.dataTask(with: url) { (data, response, error) in
        
        if error != nil {
            print("Fetch Error:")
            print(error!)
            return
        }
        
        guard let data = data, let response = response else {
            return
        }
        
        print(response)
        
        do {
            let json = try JSONDecoder().decode(Weather.self, from: data)
            
            // Store the data
            self.weather = json
            
            // Let’s check the weather
            print(self.weather)
            
            // Update the UI view
            DispatchQueue.main.async {
                self.updateView()
            }
            
            
        } catch let error {
            print("JSON Decode Error:")
            print(error)
        }
        
        
    }.resume()
}

Step 6: Defining the updateView function

func updateView() {
    temperatureLabel.text = "\(weather.temperature)℃"
    windLabel.text = weather.windSpeed + "km/hr"
    dateLabel.text = weather.date
    todayLabel.text = weather.today
    
    // Update weather icon based on status code
    // Reference: https://xml.smg.gov.mo/#Status
    
    switch weather.statusCode {
    case "01":
        weatherIcon.image = UIImage(systemName: "sun.max.fill")
    case "02", "03":
        weatherIcon.image = UIImage(systemName: "cloud.fill")
    case "12":
        weatherIcon.image = UIImage(systemName: "cloud.rain.fill")
    case "13":
        weatherIcon.image = UIImage(systemName: "cloud.heavyrain.fill")
    default:
        weatherIcon.image = UIImage(systemName: "sun.min.fill")
    }
            
}

Full Code

The ViewController.swift
we have so far:

  • IBOutlets defined
  • Weather structure defined
  • fetchWeather function
  • updateView function
class ViewController: UIViewController {

    @IBOutlet weak var weatherIcon: UIImageView!
    @IBOutlet weak var temperatureLabel: UILabel!
    @IBOutlet weak var windLabel: UILabel!
    @IBOutlet weak var dateLabel: UILabel!
    @IBOutlet weak var todayLabel: UILabel!
    
    var weather = Weather()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        
        fetchWeather()
    }
    
    func updateView() {
        temperatureLabel.text = "\(weather.temperature)℃"
        windLabel.text = weather.windSpeed + "km/hr"
        dateLabel.text = weather.date
        todayLabel.text = weather.today
        
        // Update weather icon based on status code
        // Reference: https://xml.smg.gov.mo/#Status
        
        switch weather.statusCode {
        case "01":
            weatherIcon.image = UIImage(systemName: "sun.max.fill")
        case "02", "03":
            weatherIcon.image = UIImage(systemName: "cloud.fill")
        case "12":
            weatherIcon.image = UIImage(systemName: "cloud.rain.fill")
        case "13":
            weatherIcon.image = UIImage(systemName: "cloud.heavyrain.fill")
        default:
            weatherIcon.image = UIImage(systemName: "sun.min.fill")
        }
                
    }
    
    func fetchWeather() {
        guard let url = URL(string: "https://dev.makzan.net/weather.json") else {
            return
        }
        
        URLSession.shared.dataTask(with: url) { (data, response, error) in
            
            if error != nil {
                print("Fetch Error:")
                print(error!)
                return
            }
            
            guard let data = data, let response = response else {
                return
            }
            
            print(response)
            
            do {
                let json = try JSONDecoder().decode(Weather.self, from: data)
                
                // Store the data
                self.weather = json
                
                // Let’s check the weather
                print(self.weather)
                
                // Update the UI view
                DispatchQueue.main.async {
                    self.updateView()
                }
                
                
            } catch let error {
                print("JSON Decode Error:")
                print(error)
            }
            
            
        }.resume()
    }

}


// Weather struct, we need date, temperature, humidity, windSpeed, today, statusCode

struct Weather: Decodable {
    var date = ""
    var temperature = ""
    var humidity = ""
    var windSpeed = ""
    var today = ""
    var statusCode = ""
}

Video Demo

Tab Bar Controller

Tab Bar Controller Basic

iOS Dev. Lesson 6

By makzan

iOS Dev. Lesson 6

  • 300