ios개발/프로젝트

<스위프트 프로젝트> 공공 api 받기

studying develop 2020. 3. 4. 23:07

음 ... 왜안되지

 

Codable에 대해서 이해가 필요하다. 뭐 이건 나중으로 미루고 

왜 시키는대로 했는데 안되는지 모르겠다.

 

http://apis.data.go.kr/1360000/VilageFcstMsgService/getWthrSituation
?serviceKey=
인증키(URL Encode)&numOfRows=10&pageNo=1
&
stnId=108

 

이대로 했는데 안된다.

 

아래 처럼 뜸

This XML file does not appear to have any style information associated with it. The document tree is shown below.

 

인증키를 url encode하고 전체를 url encode해야되는건가? 그냥 인증키 위치에 \(key) 를 넣고 전체를 url encode 했는데......

 

아 위에 뜬게 중요한게 아니다 그 내용을 봤어야됨;;

 

<http://apis.data.go.kr/1360000/VilageFcstMsgService/getWthrSituation?serviceKey=(내인증키)&numOfRows=10&pageNo=1&stnId=108>

 

다시 하니까 된다 ㅋㅋ

 

<response>
<header>
<resultCode>00</resultCode>
<resultMsg>NORMAL_SERVICE</resultMsg>
</header>
<body>
<dataType>XML</dataType>
<items>
<item>
<stnId>108</stnId>
<tmFc>202003041700</tmFc>
<wfSv1>
□ (종합) 오늘 중부지방(강원영동 제외)과 서해안지역 밤까지 눈 ○ (오늘) 전국 구름많음, 중부지방(강원영동 제외)과 전라도 밤까지 눈 ○ (내일) 전국 대체로 맑음 ○ (모레) 전국 대체로 맑다가 밤에 구름많아짐 □ 예상 강수량(4일 밤(24시)까지) ○ 강원영서, 충남서해안, 충북북부, 전라도, (5일까지) 울릉도.독도, 제주도산지: 5mm 미만 □ 예상 적설(4일 밤(24시)까지) ○ 강원산지, 울릉도.독도(5일까지): 1~5cm ○ 강원영서(산지 제외), 충남서해안, 충북북부, 전라서해안, 전북동부내륙, 제주도산지(5일 새벽까지): 1cm 내외 □ 유의사항 ○ (기온) 내일과 모레 아침 대부분 지역 영하권, 체감온도 낮아 춥겠음, 내륙 중심 낮과 밤 기온차 큼, 건강관리에 유의 ○ (시정, 결빙) 오늘 눈 오는 지역 가시거리 짧고, 내린 눈이 얼어 도로 미끄러운 곳, 보행자 안전사고와 교통안전 각별히 유의 ○ (강풍) 오늘과 내일, 해안과 강원산지 바람 매우 강하게 부는 곳, 그 밖의 내륙 강하게 부는 곳, 시설물 관리와 안전사고 유의 ○ (해상) 오늘부터 전해상 매우 강한 바람, 매우 높은 물결, 항해나 조업 선박 유의 ○ (너울) 내일부터 동해안 너울에 의한 높은 물결이 해안도로나 방파제를 넘는 곳, 시설물 관리와 해안가 안전사고 각별히 유의
</wfSv1>
<wn>
※ 특보 및 예비특보 발표현황은 아래의 사이트를 참고하시기 바랍니다. - 기상청 홈페이지(http://www.weather.go.kr) - 모바일(http://m.kma.go.kr) - 방재기상정보시스템(http://afso.kma.go.kr) ※ 특정관리해역 특보현황(http://afso.kma.go.kr/m/wrnSpec.jsp)
</wn>
<wr>o 없음</wr>
</item>
</items>
<numOfRows>10</numOfRows>
<pageNo>1</pageNo>
<totalCount>1</totalCount>
</body>
</response>

복붙안하고 그냥 보고 적었더니 i를 대문자로 안받아서 그랬다 ㅋㅋ

 

import UIKit


let key = "G10oWenqnE5jME3p5gBAWBmZUbjKWnQv6pQiYzx7J0coNUykWlZ3ET%2FdYworYNRhsGlniapuiW3bJofuYmwD2w%3D%3D"

//http://apis.data.go.kr/1360000/VilageFcstMsgService/getWthrSituation?serviceKey=G10oWenqnE5jME3p5gBAWBmZUbjKWnQv6pQiYzx7J0coNUykWlZ3ET%2FdYworYNRhsGlniapuiW3bJofuYmwD2w%3D%3D&numOfRows=10&pageNo=1&stnId=108
let urlString = "http://apis.data.go.kr/1360000/VilageFcstMsgService/getWthrSituation?serviceKey=\(key)&numOfRows=10&pageNo=1&stnld=108"

public struct Response: Codable{
    public let ip : String
}

public struct WeatherINF : Codable{
    var rnYn: Int  = 0 //강수형태
    var wf: String = "" //날씨
    var rnSt : Double = 0.0 //강수확률
}

if let url = URL(string : urlString){
    URLSession.shared.dataTask(with: url){ data, res, err in
        if let data = data{
            print("hey")
            let decoder = JSONDecoder()
            print(data)
            //decode is not working mabye
            if let json = try? decoder.decode(WeatherINF.self, from : data){
                print(json)
            }
        }
    }.resume()
    print("finishied")
    
}else{
    print("url is nil")
}

근데 print(json)이 안먹힌다.....음

 

 

 

 

<https://developer.apple.com/documentation/foundation/jsondecoder> 여기 보니까 decoder에 인자 타입이 json이랑 완전히 일치해야 되는거 같은데 ....;;

 

<https://developer.apple.com/documentation/foundation/jsondecoder>

여기 참조 하니까 아래 처럼 json을 선언해야 한다.

let json = """
{
    "name": "Durian",
    "points": 600,
    "description": "A fruit with a distinctive scent."
}
""".data(using: .utf8)!

 

 

이건 또 된다. 근데 문제가 내 생각에는 json이 저렇게 들어오지 않는거 같다. xml태그로 들어와서 그런가?

어떻게 해야 되는걸까!!!!!!!!!!!!!!

 

그리고 클래스를 api요청 모델은 따로 만들어도 될거같은데 url이랑 json 타입만 다르면 되잔아.

 

음 보니까 xml으로만 주는거 같다. 내가 요청한 데이터는..... 

 

찾아보니 get 인자로 &_type=json 주면 된다는데 <https://www.data.go.kr/information/QNA_0000000000014844/qna.do>

 

왜 안되냐... 저게 아니라 <http://apis.data.go.kr/1360000/VilageFcstMsgService/getWthrSituation?serviceKey=G10oWenqnE5jME3p5gBAWBmZUbjKWnQv6pQiYzx7J0coNUykWlZ3ET%2FdYworYNRhsGlniapuiW3bJofuYmwD2w%3D%3D&dataType=json&numOfRows=10&pageNo=1&stnId=108>

 

&dataType=json 으로 해야되네... xml파일 안에서 힌트를 얻었다.

 

 

기상청19_동네예보 통보문 조회서비스_오픈API활용가이드_지점목록.xlsx
0.02MB
기상청19_동네예보 통보문 조회서비스_오픈API활용가이드.docx
0.32MB

 

 

그 지금 json은 제대로 ㅇ들어오는데 , decode를 어떻게 해야 할지 모르겠다 잘 안됨 ㅋㅋ

public struct WeatherINF : Codable{
    var rnSt: Int  = 0 //강수형태
    var wf: String = "" //날씨
}


if let url = URL(string : urlString){
    URLSession.shared.dataTask(with: url){ data, res, err in
        if let data = data{
            print("hey")
            let decoder = JSONDecoder()
            
            //??
            
            print(String(decoding:data , as : UTF8.self))
            
            //decode is not working mabye
            if let json = try? decoder.decode(WeatherINF.self, from : data){
                print(json)
            }
        }
    }.resume()

}
finishied
hey
{"response":{"header":{"resultCode":"00","resultMsg":"NORMAL_SERVICE"},"body":{"dataType":"JSON","items":{"item":[{"announceTime":202003051100,"numEf":0,"regId":"11A00101","rnSt":0,"rnYn":0,"ta":5,"wd1":"W","wd2":"NW","wdTnd":"1","wf":"맑음","wfCd":"DB01","wsIt":"1"},{"announceTime":202003051100,"numEf":1,"regId":"11A00101","rnSt":10,"rnYn":0,"ta":2,"wd1":"S","wd2":"SW","wdTnd":"1","wf":"맑음","wfCd":"DB01","wsIt":"1"},{"announceTime":202003051100,"numEf":2,"regId":"11A00101","rnSt":20,"rnYn":0,"ta":7,"wd1":"SE","wd2":"S","wdTnd":"1","wf":"구름많음","wfCd":"DB03","wsIt":"1"},{"announceTime":202003051100,"numEf":3,"regId":"11A00101","rnSt":30,"rnYn":0,"ta":3,"wd1":"SE","wd2":"S","wdTnd":"1","wf":"흐림","wfCd":"DB04","wsIt":"1"},{"announceTime":202003051100,"numEf":4,"regId":"11A00101","rnSt":20,"rnYn":0,"ta":7,"wd1":"NE","wd2":"E","wdTnd":"1","wf":"구름많음","wfCd":"DB03","wsIt":"1"}]},"pageNo":1,"numOfRows":10,"totalCount":5}}}

분명 데이터의 몇몇 항목이 rnSt , wf인게 있는데 이게 json에서 네스티드라 안되는건지, 아니면 모든 항목에 대한 키가 없어서 그런지 모르겠다..

 

왜 그런지 모르겠는데 , 일단 항목이 너무 많아서 numOfRows인가를 1로 바꿔주니까 한개만 나오긴 한다.

 

swift json parsing

1. use dictionary <https://zeddios.tistory.com/153>

근데 swift4 이전 방법인듯 하다. ㅋㅋ

 

2. codable, decoder <https://learnappmaking.com/codable-json-swift-how-to/>

 

 

 

아 

The resource could not be loaded because the App Transport Security policy requires the use of a secure connection.

 

이게 떴는데 어떻게 해야지? 가능한 방법이 많은데 http를 사용하는건 비추인가?????!!?!?

 

<https://blowmj.tistory.com/entry/iOS-iOS9-App-Transport-Security-%EC%84%A4%EC%A0%95%EB%B2%95>

음 서버로 부터 인증 키가 없어서 그렇다는거 같다.

NSErrorFailingURLStringKey=http://apis.data.go.kr/1360000/ 

 

그래서 검색어를 "NSErrorFailingURLStringKey" 로 해서 아래를 찾았다.

 

<https://stackoverflow.com/questions/27531259/nserrorfailingurlstringkey-kcferrordomaincfnetwork-error-1017-for-specific-re>

 

http 파라미터에 헤더를 추가해줘야 되는건가?? 잘모르겠다!!....

 

근데 어쩃든 이렇게 검색하니 swift Error Domain=NSURLErrorDomain Code=-1022

 

<https://stackoverflow.com/questions/32631184/the-resource-could-not-be-loaded-because-the-app-transport-security-policy-requi>

 

info.plist에서 allow arbitrary load를 허용한거라 좀 불안하다. 어떤 것을 허용해야 되고 안해야 될까??

이거 말고 다른 방법으로 해보자

이제 잘 받아온다.  ->secure 하게 받자. 도메인 예외 처리를 통해서 위처럼 세팅하면 위험한듯 모든 연결을 허용하는 앱이라서.

 

잘 받아옴 ^^

 

 

 

그런데 여전히 이 부분이 안된다.

 

//decode is not working properly
if let json = try? decoder.decode(WeatherINF.self, from : data){
	self.weatherData.rnSt = json.rnSt
	print(json.rnSt)
}

 

try를 이해하고 에러를 잡자. <이 부분은 새로운 글로 작성하겠다.>

 

 

<https://stackoverflow.com/questions/32631184/the-resource-could-not-be-loaded-because-the-app-transport-security-policy-requi/33306373#33306373>

 

성공했다!!

 

 

import UIKit

/*G10oWenqnE5jME3p5gBAWBmZUbjKWnQv6pQiYzx7J0coNUykWlZ3ET%2FdYworYNRhsGlniapuiW3bJofuYmwD2w%3D%3D*/

let key = "G10oWenqnE5jME3p5gBAWBmZUbjKWnQv6pQiYzx7J0coNUykWlZ3ET%2FdYworYNRhsGlniapuiW3bJofuYmwD2w%3D%3D"

let urlString = "http://apis.data.go.kr/1360000/VilageFcstMsgService/getLandFcst?serviceKey=G10oWenqnE5jME3p5gBAWBmZUbjKWnQv6pQiYzx7J0coNUykWlZ3ET%2FdYworYNRhsGlniapuiW3bJofuYmwD2w%3D%3D&numOfRows=1&pageNo=1&regId=11A00101&dataType=json"


public struct Response: Codable{
    public let ip : String
}

public struct WeatherINF : Codable{
    var rnSt: Int  = 0 //강수형태
    var wf: String = "" //날씨
}

let jsonSample = """
{
    "rnYn" : 12,
    "wf" : "DB112",
    "rnSt" : 1.2
}
""".data(using : .utf8)!

if let url = URL(string : urlString){
    URLSession.shared.dataTask(with: url){ data, res, err in
        if let data = data{
            print("hey")
            let decoder = JSONDecoder()
            
            //??
            
            print(String(decoding:data , as : UTF8.self))
            
            //decode is not working mabye
            if let json = try? decoder.decode(WeatherINF.self, from : data){
                print(json.rnSt)
            }
        }
    }.resume()

}
else{
    print("url is nil")
}