나만의 IOS 앱개발 입문 : IOS개발 강의 흔적 남기기 7일차

박경현·2022년 3월 16일
0

드디어 7일차가 됐다!!!!
사실 시작한지 거의 4주째이지만 이제서야 7번정도 올리나보다..ㅡㅋㅋ
좀 더 열심히 올려야겠어 ㅋㅋㅋ

이번 주 중에 나만의 1년 취업 준비 로드맵을 만들어서 블로그에 올려볼거다.
결국 이 분야로 취업하고 싶어서 휴학을 선택했으니까 많은 시간을 쏟아봐야지

이번에는 드디어 API를 가져와서 쓰는 네트워크 통신을 사용한 날씨 앱이다.
사실 가장 궁금했다 웹이 아닌 APP에서는 어떤 방식으로 가져와서 구현하는지 말이다.

전체적인 틀과 사용한 스킬 설명

디자인이라고는 1도 신경 안 쓴 날씨 앱이다

오히려 스위프트에서 네트워크 통신이 어떻게 변형되어 사용 되는지 더 집중해서 볼 수 있었다.

어플 설명

  1. 텍스트필드에 도시를 적는다.
  2. 날씨가져오기라는 버튼을 클릭한다.
  3. 숨겨져있던 WeatherStackView를 보여준다
    3-1. weatherStackView에는 API통신으로 받은 도시의 날씨 상태를 알려준다

날씨 API 가져오는 법!

  1. openweather.org에서 회원가입해서 로그인 한다.
  2. currentWeatherData를 클릭하고 API doc으로 이동한다
  3. 내 아이디 클릭하고 My API Keys를 들어가서 APIKEY를 복사한다
  4. Build-in API request by city name부분으로 내려가서 한개 복사한다
  5. chrome url창에 한번 복붙해서 api를 잘 가져오는지 확인한다.
    차고로 여기서 {}이 부분은 꼭 요구하는걸 적어주자!!

메인보드 설명

매우 심플하다 -> 솔직히 디자인 실력은 이 강의로는 절대 안늘것같다..

weatherStackView같은 경우 StackView로 묶어서 isHidden을 단체로 할수있게 해놨다. => 이러면 안에 내용이 같이 사라지고 같이 나타남

코드 리뷰

구조체를 두 개를 썼다
-> 에러메세지를 가져와서 우리 입맛대로 만드는 ErrorMessage구조체
-> 날씨 정보를 가져오는 WeatherInformation구조체

ErrorMessage 구조체

iompormation Foundation

strunct ErrorMessage: Codable {
	let message: String
}

이번 수업에서는 Codable이 핵심이다!!!!!!!!!

codable이란 밖에 있는 데이터를 가져오고 밖에 데이터를 내보낼 때 사용하는 녀석이다

쉽게 말해서 JSON파일을 가져온다고 가정해보자!!

public typealias Codable = Decodable & Encodable -> 이게 정의!!

Decodable은 자신이 가져온 데이터를 JSON형태 ==> 내가 원하는 모델로 바꿈
Encodable은 내 데이터를 JSON형태로 바꾸는 거다

차고로 JSON에서 쓴 Key값과 여기 구조체의 프로퍼티 이름이 다르면 조금 특별한 방식을 추가해서 연결해주어야한다!!

weatherInformation 구조체

import Foundation

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

struct Wheather: Codable{
	let id: Int
    let main: String
    let description: String
}
struct Temp: Codable {
	let temp: Double
    let fellsLike: Double
    let minTemp: Double
    let maxTemp: Double
    
    enum CodingKeys: String, CodingKey {
    	case temp
        case feelsLike = "feels_like"
        case minTemp = "temp_min"
        cse maxTemp = "temp_max"
    }
}

구조체안에 CodingKeys라는 enum을 적어준게 있는데 이거는 우리가 가져온 JSON파일과 키값을 다르게 정의했을때 적어준다.

Codable과 마찬가지로 프로토콜 형태이다.
CodingKeys에서 JSON파일의 키는 문자열이어서 String도 상속했다.

weather는 [Wheather]타입의 배열을 선언했다?

메인 코드 리뷰

변수

@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!

마지막에 적은 weatherStackView는 isHidden을 통해 날씨 정보를 정확한 도시를 입력했을때만 보여준다.

차고로 @는 컴파일러에게 어떤 속성(attribute)을 가지고있는지 알려주는 예약어이다ㅎ

함수

override func viewDidLoad(){
	super.viewDidLoad()
    
}
@IBAction func tapfetchWeatherButton(_ sender: UIButton){
	if let cityName = self.cityNameTextField.text {
    	self.getCuttentWeather(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))"
    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)
}

func getCurrentWeather(cityName: String){
	guard let url = URL(string: "https://api.openweathermap.org/data/2.5/weather?q=\(cityName)&appid=7abb9a0098b73369439dd73ccbfb3512"
    let session = URLSession(configuration: .dafault)
    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)
            }
        }
        
        
    }.resume()
}

tapfetchWeatherButton 함수

도시 이름을 API로 전달하는 역할을 하는 getCurrentWeather함수를 호출하는 함수다.

추가로 endEditing을 해서 textField를 제외한 나머지를 편집불가 상태로 변형시켰다.

configureView 함수

말 그대로 화면에 어떻게 보여줄지, 코드로 무슨 정보를 받아서 보여줄지 정하는 함수이다.
구조체를 들어가는 방식이 상당히 흥미로움!

weatherInformation안에 temp라는 구조체가 있고 temp는 Temp타입으로 그 안에 temp가 또 있다 ==>> 그래서 weatherInformation.temp.temp로 호출했다!!!!

차고로 getCurrentWeather에서 configure를 부른다!!
그 이유는 아마도 JSON파일을 decoder함 정보를 전달해줘야하기 때문인거같다

showAlert 함수

잘못된 도시를 입력했을때 경고창을 띄운다는 역할을 하는 함수다.

self.present(alert, animated: true) -> 이거는 이 함수가 불러지면 함수 안에서 설정한 alert가 실행되게 한다!!
즉 화면이동처럼 화면에 경고창 표시!!!

getCurrentWeather함수

여기는 내가 모르는 정보들이 많아서 따로 블로그로 작성하겠다.

후기

항상 느끼는 거지만 구조체를 불러올때 따로 import 하지 않아도 되는건 좀 편하다
네트워크 통신은 매우 중요한 부분이기 때문에 이 코드안에서 쓰인 내용을 전부다 분석하는데 지금부터 3시간은 쓸 예정이다
이해하고 한번 블로그로 작성해봐야지 ㅎㅎ

profile
SW로 문제를 해결하려는 열정만 있는 대학생

0개의 댓글