일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
Tags
- UIAlertAction
- font book
- 한국어 개인정보처리방침
- xcode로 날씨앱 만들기
- MKMapItem
- dispatchsource
- 러닝기록앱
- Startign Assignments
- 서체관리자
- addannotation
- App Store Connect
- swift
- weak var
- Protocol
- 클로저의 캡슐화
- CLLocationManagerDelegate
- 영문 개인정보처리방침
- 러닝타이머
- Timer
- Required Reason API
- SwiftUI Boolean 값
- MKMapViewDelegate
- Xcode
- UICollectionViewFlowLayout
- 단일 책임원칙
- RunningTimer
- AnyObject
- CoreLocation
- weatherKit
- WeatherManager
Archives
- Today
- Total
VesselWheel
3시간 단위 5일치 OpenWeatherMap API를 활용한 데이터 호출 본문
기존에 WeatherData를 활용한 현재 날씨 API는 위경도 혹은 도시지역의 현재 날씨 기준으로 실시간 기상예보이다.
// MARK: - public Methods
//현재 날씨정보 : LocationManager에서 위치정보를 받고, 위경도 API에 적용한 후, 날씨 데이터 값 복사 : 독립적인 인스턴스 생성
//https://api.openweathermap.org/data/2.5/weather?lat=37.565534&lon=126.977895&appid=3a33f61058f414d02d09e88bfa83117c
public func getLocationWeather(latitude: Double, longitude: Double, completion: @escaping(Result<WeatherData, NetworkError>) -> Void) {
LocationManager.shared.setLocation(latitude: latitude, longitude: longitude)
guard let currentLocation = LocationManager.shared.currentLocation else {
return completion(.failure(.badLocation))
}
guard let url = URL.urlForWeatherForLocation(currentLocation, apiKey: apiKey) else {
return completion(.failure(.badUrl))
}
performRequest(with: url, completion: completion)
}
// OpenWeatherMap에서 지원하는 도시 검색 사이트 https://openweathermap.org/find?q
// 현재 날씨정보의 도시 기준, url test(인천) : https://api.openweathermap.org/data/2.5/weather?q=incheon&appid=3a33f61058f414d02d09e88bfa83117c
public func getCityWeather(city: String, completion: @escaping(Result<WeatherData, NetworkError>) -> Void) {
let formattedCity = city.replacingOccurrences(of: " ", with: "+")
guard let url = URL.urlForWeatherFor(formattedCity, apiKey: apiKey) else {
return completion(.failure(.badUrl))
}
performRequest(with: url, completion: completion)
}
하지만 날씨앱의 3시간 단위 5일치(무료 API 기준)을 하려면, WeatherData 모델이 해당 API에 맞게금 변경을 해주어야 한다.
3시간 단위 5일치 날씨예보 API call test :
test API call : api.openweathermap.org/data/2.5/forecast?lat=37.4536&lon=126.7317&appid=3a33f61058f414d02d09e88bfa83117c
상기 기준 API call의 데이터 모델 : ForecastWeatherData
더보기
// This file was generated from JSON Schema using quicktype, do not modify it directly.
// To parse the JSON, add this file to your project and do:
//
// let forecastWeatherData = try? JSONDecoder().decode(ForecastWeatherData.self, from: jsonData)
import Foundation
// MARK: - ForecastWeatherData
struct ForecastWeatherData: Codable {
let cod: String
let message, cnt: Int
let list: [List]
let city: City
}
// MARK: - City
struct City: Codable {
let id: Int
let name: String
let coord: Coord
let country: String
let population, timezone, sunrise, sunset: Int
}
// MARK: - Coord
struct Coord: Codable {
let lat, lon: Double
}
// MARK: - List
struct List: Codable {
let dt: Int
let main: MainClass
let weather: [Weather]
let clouds: Clouds
let wind: Wind
let visibility: Int
let pop: Double
let sys: Sys
let dtTxt: String
let rain: Rain?
enum CodingKeys: String, CodingKey {
case dt, main, weather, clouds, wind, visibility, pop, sys
case dtTxt
case rain
}
}
// MARK: - Clouds
struct Clouds: Codable {
let all: Int
}
// MARK: - MainClass
struct MainClass: Codable {
let temp, feelsLike, tempMin, tempMax: Double
let pressure, seaLevel, grndLevel, humidity: Int
let tempKf: Double
enum CodingKeys: String, CodingKey {
case temp
case feelsLike
case tempMin
case tempMax
case pressure
case seaLevel
case grndLevel
case humidity
case tempKf
}
}
// MARK: - Rain
struct Rain: Codable {
let the3H: Double
enum CodingKeys: String, CodingKey {
case the3H
}
}
// MARK: - Sys
struct Sys: Codable {
let pod: Pod
}
enum Pod: String, Codable {
case d = "d"
case n = "n"
}
// MARK: - Weather
struct Weather: Codable {
let id: Int
let main: MainEnum
let description: Description
let icon: Icon
}
enum Description: String, Codable {
case brokenClouds = "broken clouds"
case clearSky = "clear sky"
case lightRain = "light rain"
case overcastClouds = "overcast clouds"
}
enum Icon: String, Codable {
case the01D = "01d"
case the01N = "01n"
case the04D = "04d"
case the04N = "04n"
case the10D = "10d"
case the10N = "10n"
}
enum MainEnum: String, Codable {
case clear = "Clear"
case clouds = "Clouds"
case rain = "Rain"
}
// MARK: - Wind
struct Wind: Codable {
let speed: Double
let deg: Int
let gust: Double
}
ForecastWeatherData을 활용한 API 호출 매소드
// https://openweathermap.org/forecast5 5일치 3시간 단위 일기예보
//test API call : api.openweathermap.org/data/2.5/forecast?lat=37.4536&lon=126.7317&appid=3a33f61058f414d02d09e88bfa83117c
public func getForecastWeather(latitude: Double, longitude: Double, completion: @escaping(Result<ForecastWeatherData, NetworkError>) -> Void) {
LocationManager.shared.setLocation(latitude: latitude, longitude: longitude)
guard let currentLocation = LocationManager.shared.currentLocation else {
return completion(.failure(.badLocation))
}
guard let url = URL.urlForForecastForLocation(currentLocation, apiKey: apiKey) else {
return completion(.failure(.badUrl))
}
performRequestForecast(with: url, completion: completion)
}
URL을 extension으로 구분하여 코드의 가독성을 높였다.
더보기
//
// URL+Extension.swift
// Weather777
//
// Created by Jason Yang on 2/13/24.
//
import Foundation
import CoreLocation
extension URL {
//위, 경도 API call
//https://openweathermap.org/current
static func urlForWeatherForLocation(_ currentLocation: CLLocationCoordinate2D, apiKey: String) -> URL? {
guard let url = URL(string: "https://api.openweathermap.org/data/2.5/weather?lat=\(currentLocation.latitude)&lon=\(currentLocation.longitude)&appid=\(apiKey)") else {
return nil
}
return url
}
//도시 기준 API call
//https://openweathermap.org/current
static func urlForWeatherFor(_ city: String, apiKey: String) -> URL? {
guard let url = URL(string: "https://api.openweathermap.org/data/2.5/weather?q=\(city)&appid=\(apiKey)") else {
return nil
}
return url
}
//5일치 3시간 단위 날씨 예보 API call
//https://openweathermap.org/forecast5
static func urlForForecastForLocation(_ currentLocation: CLLocationCoordinate2D, apiKey: String) -> URL? {
guard let url = URL(string: "https://api.openweathermap.org/data/2.5/forecast?lat=\(currentLocation.latitude)&lon=\(currentLocation.longitude)&appid=\(apiKey)") else {
return nil
}
return url
}
// //Air Pollution API
// //https://openweathermap.org/api/air-pollution
// static func urlForAirPollutionForLocation(_ currentLocation: CLLocationCoordinate2D, apiKey: String) -> URL? {
// guard let url = URL(string: "http://api.openweathermap.org/data/2.5/air_pollution?lat=\(currentLocation.latitude)&lon=\(currentLocation.longitude)&appid=\(apiKey)") else {
// return nil
// }
// return url
// }
//
// //Geocoding API
// //https://openweathermap.org/api/geocoding-api
// static func urlForGeoDirect(_ city: String, stateCode: String, countryCode: String, limit: Int, apiKey: String) -> URL? {
// guard let url = URL(string: "http://api.openweathermap.org/geo/1.0/direct?q=\(city),\(stateCode),\(countryCode)&limit=\(limit)&appid=\(apiKey)") else {
// return nil
// }
// return url
// }
//
// //Weather Maps 1.0
// //https://openweathermap.org/api/weathermaps
// static func urlForMapLayer(_ layer: String, z: Int, x: Int, y: Int, apiKey: String) -> URL? {
// guard let url = URL(string: "https://tile.openweathermap.org/map/\(layer)/\(z)/\(x)/\(y).png?appid=\(apiKey)") else {
// return nil
// }
// return url
// }
}
- OpenWeatherMap 은 현재날씨, 5일치 날씨예보, 미세먼지, 지역, 날씨맵 API도 지원한다.
'Xcode Study' 카테고리의 다른 글
5일치 3시간 단위 날씨예보 배열에 넣기(with OpenWeatherMap) (2/2) (0) | 2024.02.15 |
---|---|
5일치 3시간 단위 날씨예보 배열에 넣기(with OpenWeatherMap) (1/2) (0) | 2024.02.13 |
[trouble Shooting]지원하지 않는 5일 단위 OpenWeatherMap API call (0) | 2024.02.12 |
싱글톤 패턴과 델리게이트 패턴 적용에 대한 고찰(with 날씨, 위치 데이터) (0) | 2024.02.09 |
API key 값 사용시, 외부 노출 방지 방법(with 날씨앱) (0) | 2024.02.09 |