티스토리 뷰

https://world-of-larooly.tistory.com/24

 

Swift 날씨 api 연결해보기 1단계

이번에는 사용자의 지역에 따른 날씨를 가져올 일이 생겨서 한번 만들게 되었는데 저처럼 "이걸 어떻게 해야 하지?" 하시는 분들을 위해 올려봅니다. 참고로 이번 포스트는 따라하시기 전에 준

world-of-larooly.tistory.com

일단 길이 너무 길어진 관계로 

let apiKey = "인증키를 넣어주세요"
let apiUrl = "(End Point를 넣어주시면 됩니다.)/getVilageFcst?"

여기까지 하셨다는 전제하에 진행하도록 하겠습니다.

(아직 위 단계가 안끝나신분들은 위 글을 먼저 보고 오시길 추천드립니다.)

 

이제 저희는 우리가 어디있고 오늘 날짜가 언제인지 찾아 넣어줘야 합니다.

 

참고로 base_time이라는 걸 같이 넣어줘야하는데 이 시간은  반드시 

"0200","0500","0800","1100","1400","1700","2000","2300" 이 중에서 넣어야 작동합니다. 

 

일단 본격적인 시작전에 필요한거 전부 import 하고 시작합시다. 

import Foundation
import UIKit
import Alamofire
import CoreLocation
import ObjectMapper
// 이중에서 안뜨시는게 있다면 CoCoaPod 를 확인해주세요.

그럼 필요한 함수를 하나씩 넣어보겠습니다. 

 

1. 위치정보 -> 격자 

- 아래 식을 사용하면 사용자의 위치를 가져올수있습니다. 

var mapManager : CLLocationManager! // 맨위에 선언해주세요.


   func getGpsLocation() -> (Double,Double){// 사용자 위치정보 가져오기
        mapManager = CLLocationManager()
        mapManager.delegate = self
        mapManager.requestWhenInUseAuthorization()
        mapManager.desiredAccuracy = kCLLocationAccuracyBest
        mapManager.startUpdatingLocation()
        let coor = mapManager.location?.coordinate
        var lat = coor?.latitude
        var long = coor?.longitude
        return (lat,long) as! (Double, Double)
    }
    
    func convertGPStoGRID( lat_X: Double, lng_Y: Double) -> (Int,Int) {// 위경도 -> 격자
        let RE = 6371.00877 // 지구 반경(km)
        let GRID = 5.0 // 격자 간격(km)
        let SLAT1 = 30.0 // 투영 위도1(degree)
        let SLAT2 = 60.0 // 투영 위도2(degree)
        let OLON = 126.0 // 기준점 경도(degree)
        let OLAT = 38.0 // 기준점 위도(degree)
        let XO:Double = 43 // 기준점 X좌표(GRID)
        let YO:Double = 136 // 기1준점 Y좌표(GRID)
        
        let DEGRAD = Double.pi / 180.0
    
        let re = RE / GRID
        let slat1 = SLAT1 * DEGRAD
        let slat2 = SLAT2 * DEGRAD
        let olon = OLON * DEGRAD
        let olat = OLAT * DEGRAD
        
        var sn = tan(Double.pi * 0.25 + slat2 * 0.5) / tan(Double.pi * 0.25 + slat1 * 0.5)
        sn = log(cos(slat1) / cos(slat2)) / log(sn)
        var sf = tan(Double.pi * 0.25 + slat1 * 0.5)
        sf = pow(sf, sn) * cos(slat1) / sn
        var ro = tan(Double.pi * 0.25 + olat * 0.5)
        ro = re * sf / pow(ro, sn)

        var ra = tan(Double.pi * 0.25 + (lat_X) * DEGRAD * 0.5)
        ra = re * sf / pow(ra, sn)
        var theta = lng_Y * DEGRAD - olon
        if theta > Double.pi {
            theta -= 2.0 * Double.pi
        }
        if theta < -Double.pi {
            theta += 2.0 * Double.pi
        }
        
        theta *= sn
        let x = Int(floor(ra * sin(theta) + XO + 0.5))
        let y = Int(floor(ro - ra * cos(theta) + YO + 0.5))
        return (x,y)
    }

 

2. 시간 체크용 함수 

    var totalURL = ""
    var nowTimeString = ""// 실제시간
    var baseTimeString = ""// 측정 발표 시간
    var fstTimeString = ""//예상 측정 시간
    // 마찬가지로 애네도 위에 선언해주세요.


    func getCheckTime() -> String {
        return getIndexString(text: baseTimeString, startIndex: 8, endIndex: 12)
    }
    func getCheckDate() -> String {
        return getIndexString(text: baseTimeString, startIndex: 0, endIndex: 8)
    }
    func getThreeTimesByString(getDate : Date){ // 시간을 가져와 문자로 만드는 부분입니다.
        let dateFormatter = DateFormatter()
        // Set Date Format
        dateFormatter.dateFormat = "YYYYMMddHHmm"
        nowTimeString = dateFormatter.string(from: getDate)
        fstTimeString = getIndexString(text: nowTimeString, startIndex: 0, endIndex: 10) + "00"
        baseTimeString = getBaseTimeString()
    }
    
    // 글자를 자리수로 자르는 함수입니다.
    func getIndexString(text : String,startIndex : Int , endIndex : Int) -> String {
        let startIndex = text.index(text.startIndex, offsetBy: startIndex)// 사용자지정 시작인덱스
        let endIndex = text.index(text.startIndex, offsetBy: endIndex)// 사용자지정 끝인덱스
        return String(text[startIndex ..< endIndex])
    }
    
    func getBaseTimeString() -> String {
        //ex) 20220517  -> 202205162300, 202205170200, 202205170500
        let nowDateString = getIndexString(text: nowTimeString, startIndex: 0, endIndex: 8)
        let upTimeLine = ["2300","0200","0500","0800","1100","1400","1700","2000"]
        let yesterDayInt = Int(nowDateString)! - 1
        let yesterDayString = String(yesterDayInt)
        var timeArray : [Int] = []
        for i in 0..<upTimeLine.count {
            var newTimeElemt : String
            if(i == 0){
                newTimeElemt = yesterDayString + upTimeLine[i]
            }else{
                newTimeElemt = nowDateString + upTimeLine[i]
            }
            timeArray.append(Int(newTimeElemt)!)
        }
        let nowTimeInt = Int(nowTimeString)!
        for i in 0..<timeArray.count {
            if(timeArray[i] > nowTimeInt){
                if(i > 0){ // 시간차이가 얼마 안날때 i> 0
                    if(nowTimeInt - timeArray[i-1] < 100){
                        return String( timeArray[i-2] )
                    }else{
                        return String( timeArray[i-1] )
                    }
                }else{
                    return String( timeArray[i-1] )
                }
            }
        }
        return String( nowTimeInt ) // 일단 여기까지 오는 일은 거의 없습니다.
    }

3. 열심히 합치기 

 func getWeatherApiUrl(time : Date , grid : (Int,Int))-> String{
        var weatherUrl = apiUrl + "serviceKey=" + apiKey
        weatherUrl += "&pageNo=1&numOfRows=1000&dataType=JSON&base_date="
        weatherUrl += getCheckDate()
        weatherUrl += "&base_time=\(getCheckTime())&nx=\(grid.0)&ny=\(grid.1)"
        return weatherUrl
    }

위 함수식을 추가해주시고 아래 처럼 URL 을 만들면 드디어 통신용 URL 을 다 만들었습니다. 

getThreeTimesByString(getDate: Date.now)
        
totalURL = getWeatherApiUrl(time: Date.now, grid: convertGPStoGRID(lat_X: getGpsLocation().0, lng_Y: getGpsLocation().1))

4. 실제 URL 에서 JSON 가져오기 

- 이제 Alamofire를 통해 Json 값을 가져오시면 됩니다. 

self.weatherAlamofire()
func weatherAlamofire(){
        print(totalURL)
        AF.request(totalURL).responseData{ response in
            switch response.result {
                case .success(let data):
                    do {
                        print(response.data)
                        let asJSON = try JSONSerialization.jsonObject(with: data)
                       	//여기에 JSON 값이 나오게 됩니다. 
                       
                    } catch {
                        print("Error while decoding response: \(error) from: \(String(data: data, encoding: .utf8))")
                    }
                case .failure(let error):
                    print("Error get Value from Server")
                    break
                    // Handle as previously error
                }
        }
    }

그런데 JSON으로 가져온 값을 어떻게 이용하는걸까요?

 

그 방법에 대해서는 3단계에서 알아보도록 하겠습니다. 

코드만 보고 싶으신 분들을 위해 3단계 이후 전체 코드를 설명없이 올릴 예정입니다. 

참고해주시면 될 것 같습니다.

 

그럼 3단계에서 뵙겠습니다. 

댓글