(iOS)날씨 앱 만들기

박준수·2022년 4월 24일
2

iOS Basic

목록 보기
7/7
post-thumbnail

기능 상세

  • 도시 이름을 입력하면 현재 날씨 정보를 가져와 화면에 표시되게 한다.
  • 도시 이름을 잘못 입력하면 서버로부터 응답 받은 에러 메시지가 alert 로 표시되게 한다.

활용 기술

  • Current Weather API
  • URLSession

URLSession

특정한 url 을 이용하여 데이터를 다운로드하고 업로드하기 위한 API

URLSession Life Cycle

  1. Session Configuration을 결정하고 Session 을 생성
  2. 통신할 URLRequest 객체를 설정
  3. 사용할 Task 를 결정하고 그에 맞는 Completion HandlerDelegate 메소드를 작성
  4. 해당 Task 를 실행
  5. Task 완료 후 Completion Handler 클로저 호출

Current Weather API

https://openweathermap.org

위의 사이트에서 제공하는 공공 API를 사용하여 특정 도시의 현재 날씨 정보를 불러올 수 있도록 구현

구현

  • URLSession 을 사용하여 읽어온 JSON 데이터와 구조체를 매핑시키기 위해 Codable 프로토콜 사용
    - JSON 데이터에서 불러온 key 가 아닌 다른 이름으로 지정하여 사용하고 싶을 때 CodingKey 프로토콜 사용

WeatherInformation.swift

struct WeatherInformation: Codable {
    let weather: [Weather]
    let temp: Temp
    let name: String
    
    enum CodingKeys: String, CodingKey {
        case weather
        case temp = "main"
        case name
    }
}

struct Weather: Codable {
    let id: Int
    let main: String
    let description: String
    let icon: String
}

struct Temp: Codable {
    let temp: Double
    let feelsLike: Double
    let minTemp: Double
    let maxTemp: Double
    
    enum CodingKeys: String, CodingKey {
        case temp
        case feelsLike = "feels_like"
        case minTemp = "temp_min"
        case maxTemp = "temp_max"
    }
}

ErrorMessage.swift

struct ErrorMessage: Codable {
    let message: String
}

ViewController

class ViewController: UIViewController {
    @IBOutlet weak var cityNameTextField: UITextField!
    @IBOutlet weak var cityNameLabel: UILabel!
    @IBOutlet weak var weatherDescriptionLabel: UILabel!
    @IBOutlet weak var tempLabel: UILabel!
    @IBOutlet weak var maxTempLabel: UILabel!
    @IBOutlet weak var minTempLabel: UILabel!
    @IBOutlet weak var weatherStackView: UIStackView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
    }
    
    @IBAction func tapFetchWeatherButton(_ sender: UIButton) {
        if let cityName = self.cityNameTextField.text {
            self.getCurrentWeather(cityName: cityName)
            self.view.endEditing(true)
        }
    }
    
    func configureView(weatherInformation: WeatherInformation) {
        self.cityNameLabel.text = weatherInformation.name
        if let weather = weatherInformation.weather.first {
            self.weatherDescriptionLabel.text = weather.description
        }
        self.tempLabel.text = "\(Int(weatherInformation.temp.temp - 273.15))°C"
        self.minTempLabel.text = "최저: \(Int(weatherInformation.temp.minTemp - 273.15))°C"
        self.maxTempLabel.text = "최고: \(Int(weatherInformation.temp.maxTemp - 273.15))°C"
    }
    
    func showAlert(message: String) {
        let alert = UIAlertController(title: "에러", message: message, preferredStyle: .alert)
        alert.addAction(UIAlertAction(title: "확인", style: .default, handler: nil))
        self.present(alert, animated: true, completion: nil)
    }
    
    func getCurrentWeather(cityName: String) {
        guard let url = URL(string: "https://api.openweathermap.org/data/2.5/weather?q=\(cityName)&appid={api key}") else { return }
        let session = URLSession(configuration: .default)
        session.dataTask(with: url) { [weak self] data, response, error in
            let successRange = (200..<300)
            guard let data = data, error == nil else { return }
            let decoder = JSONDecoder()
            if let response = response as? HTTPURLResponse, successRange.contains(response.statusCode) {
                guard let weatherInformation = try? decoder.decode(WeatherInformation.self, from: data) else { return }
                DispatchQueue.main.async {
                    self?.weatherStackView.isHidden = false
                    self?.configureView(weatherInformation: weatherInformation)
                }
            } else {
                guard let errorMessage = try? decoder.decode(ErrorMessage.self, from: data) else { return }
                DispatchQueue.main.async {
                    self?.showAlert(message: errorMessage.message)
                }
            }
        }.resume()
    }
}

최종 화면



출처

패스트캠퍼스, 초격차 패키지 : 30개 프로젝트로 배우는 iOS 앱 개발 with Swift

profile
안녕하세요!!

0개의 댓글