잡초의 일지

[Swift] [SwiftUI] 기상청 API 이용한 날씨 앱 [정리본] 본문

Just for fun/iOS

[Swift] [SwiftUI] 기상청 API 이용한 날씨 앱 [정리본]

JabCho 2021. 1. 10. 14:32
728x90
반응형
SMALL

최종 결과 깃헙 -> 현재 잠시 private으로 해 놓았다.

주의!

이 api는 지난 데이터 관측만 제공하고, 예측은 제공하지 않는다.

즉, 시시각각 변하는 데이터가 아닌, 1시간 단위의 데이터를 제공한다.

 

또한, 모든 데이터형이 String으로 변하였다. -> 이 점이 예전에 작동하던 코드가 작동하지 않았던 이유 같다.

개요

기상청 api를 사용한 날씨앱을 만들게 된 계기는 이렇다.

비가 많이 오던 장마철이라 날씨앱을 만들고 싶다는 생각을 하고 찾아보게 되었다.

openweatherapi를 이용하여 만드는 예시는 아주 많이 있었다. 하지만 이것은 외국 사이트였고, 서울과 부산같은 큰 도시의 정보만 있었다.

그래서 기상청의 api가 있을것이라는 생각이 들어, 한국의 데이터를 사용해보자! 라는 생각으로 만들게 되었다.

 

alicecodealice.tistory.com/121

 

[Swift] [SwiftUI] 기상청 API 이용한 날씨 앱 (초본)

완성본 여기에 완성본을 만들어서 링크를 올려놓을 것이다. 기상청 api를 사용 할 때 유의하여야 할 점 : 1. 시시각각 변하는 정보를 주지 않는다. 1시간 단위의 정보를 준다. --> 이게 가장 띠용이

alicecodealice.tistory.com

 

UI 계획과 구상 -> UI를 이쁘게 고치는것은 아직 계획 단계에 있다.

(다른 하고싶은것들이 많아서 ㅎ)

더보기

이번에는 UI를 구체적으로 정하였으니, UI 를 먼저 만든 후 아래와 같은 순서로 진행하도록 하겠다.

  1.  UI를 통하여 사용자가 원하는 값을 읽어들인다.
  2. 그 값을  url에 넣고 요청한다
  3. json 파일의 정보를 불러와 디바이스에 표시한다.

 

코드와 실행결과

 - UI 부분

구상한 대로 만들고, 캔버스를 통해 확인하였다. 

api를 통한 정보를 필요로 하는 곳은 예시로 임의의 값을 넣어두었다.

 

import SwiftUI

struct ContentView: View {
    var body: some View {
        
        NavigationView {
            VStack{
                HStack{
                    Spacer()
                    NavigationLink(destination: SettingView()){
                        Image(systemName: "gear").font(.system(size: 30))
                    }.navigationBarTitle("날씨를 찾아서")
                }
                .padding(.trailing, 10.0)
                
                Spacer()
                
                VStack(alignment: .center, spacing: 30.0){
                    Image(systemName: "sun.min.fill").font(.system(size: 100)).padding()
                    Text("40.5도씨")      // 임의로 정한 이 값들은, SettingView에서 정한 값을 ViewModel에 준 후,
                    Text("2020년02월02일") // Model에서 계산이 끝난 후, 다시 그 계산이 끝난 값을 ViewModel에 주고,
                    Text("서울")           // 이제 ViewModel에 있는 값을 View에 표현한다. 이런 방식으로 한다. 따라서 지금 바꾸지 않았다.
                        .font(.largeTitle)
                        .fontWeight(.semibold)
                }
                
                Spacer()
            }
        }

    }
}



struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

<메인 화면>

 

 

import SwiftUI

struct SettingView: View {
    
    let hours = Hours
    let loc = locationName.sorted()
    @State var selectedLoc: Int = 0
    @State var selectedDate: Date = Date()
    @State var selectedHour: Int = 0
    
    var body: some View {
            VStack{
                Form{
                    NavigationLink(destination: DetailSetting() ){ // 강수량, 풍량 등을 toggle 스위치로 조절하여 디바이스 화면에 해당 정보 표시.
                            Text("세부 날씨정보 설정")
                    }.navigationBarTitle("설정")
                    
                    Section(header: Text("지역 변경")){
                        Picker(selection: $selectedLoc, label: Text("")){
                            ForEach(0 ..< loc.count){
                                Text(self.loc[$0])
                            }
                        }
                        .pickerStyle(WheelPickerStyle())
                        .frame(alignment: .center)
                        
                        Text("지역명: \(loc[selectedLoc])")
                    }
                    
                    Section(header: Text("날짜 고르기")) {
                        DatePicker("", selection: $selectedDate, displayedComponents: .date)
                        .frame(alignment: .center)
                    }
                    
                    Section(header: Text("시간 고르기")){
                        Picker("", selection: $selectedHour) {
                            ForEach(0 ..< hours.count) {
                                Text(self.hours[$0])
                            }
                        }.pickerStyle(WheelPickerStyle())
                        .frame(alignment: .center)
                    }
                }
                
                Button(action: {
                    // Data 얻어오기.
                }){
                    Text("변경내용 저장하기")
                        .background(Color.red)
                }
                
            }
        
    }
}

struct SettingView_Previews: PreviewProvider {
    static var previews: some View {
        SettingView()
    }
}

<설정>

 

 

import SwiftUI

struct DetailSetting: View {
    
    @State var rain = true
    @State var wind = false
    @State var ta = true
    
    var body: some View {
        Form{
            Section{
                Toggle(isOn: $rain){
                    Text("강수량")
                }.padding()
            }
            Section{
                Toggle(isOn: $wind){
                    Text("풍량")
                }.padding()
            }
            Section{
                Toggle(isOn: $ta){
                    Text("기온")
                }.padding()
            }
            Section{
                Toggle(isOn: /* 다른것의 변수 이름 넣기 */){
                    Text("또다른것 추가..")
                }.padding()
            }
            
        }
    }
}

struct DetailSetting_Previews: PreviewProvider {
    static var previews: some View {
        DetailSetting()
    }
}

<세부설정>

 

 

대략적으로 틀을 잡으니, 이런 모양이다.

 

MARK: MVVM중 View 완성(변경가능성있음)

TODO

- Model과 ViewModel, API 네트워킹 부분 만들기

- 날씨에 맞는 이모지

- 사용자가 바꾼 값을 토대로 데이터를 가져온 후 그 데이터를 표시

 

API와 네트워킹 부분

[만났던 오류들과 해결방법]

더보기

1. url이 제대로 나타나지 않는다. (URLComponents와 URLQueryItem이용하여 만듦.)

sesang06.tistory.com/123

 

Swift 에서 한글, 특수문자 엔드포인트를 적절히 인코딩하기

Swift에서의 한글, 특수문자 엔드포인트를 적절히 URL Encoding하기 https url에 엔드포인트로 한국어를 사용했을 때, 습관적으로 이렇게 코딩하곤 합니다. import Foundation var url = URL(string: "https://se..

sesang06.tistory.com

ViewModel과 Model 부분을 만들면서,  URL을 다루는 많은 방법들을 보았다.

URLComponents를 이용하여 scheme, host, path를 정하고 queryItems로 쉽게  url을 구성해 보려고 했지만,

자꾸 내용이 출력되지 않아 이상했다.

이유는 url에 있었다. 위의 포스팅을 본다면, 예약문자가 아닌 %가 있어서 발생하는것 같다. 

 따라서 이 부분을 고쳐야 한다.

www.djackson.org/why-we-do-not-use-urlcomponents/

 

Why we do not use URLComponents

The short version? Because it doesn’t do its job escaping content.

www.djackson.org

이것을 읽어보니,  URLComponents를 사용하면서 이 문제를 해결하는 방법이 있는듯 하다. (예외사항을 정해주는듯 하다.)

 

간단히 한줄을 추가하는것으로 해결되었다.

 

2. 데이터가 제대로 불려졌는지 단순히 확인을 하는 용도의 print가 나타나지 않는다. (func 까지는 접근하는데, 그 안에서 오류가 나는듯 하다.)

데이터가 nil인 경우 디폴트 설정을 해주어야 한다.

 

[유의사항]

기상청 페이지는 https가 아닌 http를 사용하기 때문에 info.plist에서 설정을 해주어야 한다.

이것은 구글링을 하면 여러 자료가 나온다.

www.hahwul.com/2019/03/11/ios-app-http-app-trasport-security/

 

iOS App에서 HTTP 통신 허용하기(+App Trasport Security란?)

Security engineer, Developer and H4cker

www.hahwul.com

 

최종 결과 깃헙 -> 현재 잠시 private으로 해 놓았다.

 

여기서  YOUR_KEY 부분에 자신이 발급받은 키를 넣으면 된다.

모두 자신의 신상정보를 잘 지키도록 하자.

지인분께서 소스코드를 올리며 key를 깃헙에 올렸다가 통장에서 돈이 빠져나갔다고 한다...ㅎㄷㄷ

 

==================================================================================

 

Picker 에서 시간을 정할 때, 여러번 클릭하면 오류가 생긴다. 이 부분은 고쳐야 한다.

728x90
반응형
LIST
Comments