事前準備
APIキーの取得
事前にOpenWeather
のページで個人のAPIキーを取得しておきましょう (無料)
ライブラリのインストール
今回は、Alamofire
, SwiftyJSON
を使用します。(CoreLocation
はXcodeに元から入っているのでインストール不要)
pod 'Alamofire'
pod 'SwiftyJSON', '~> 4.0'
コード
Model (モデル)
import Foundation
struct WeatherData {
var temperature: Double // 気温
var description: String // 説明
var locationName: String // 場所
init(temperature: Double, description: String, locationName: String) {
self.temperature = temperature
self.description = description
self.locationName = locationName
}
}
View (ビュー)
import SwiftUI
struct HomeView: View {
@ObservedObject private var viewModel = HomeViewModel()
var body: some View {
NavigationView {
VStack {
List(viewModel.weatherData, id: \.temperature) { data in
VStack(alignment: .leading) {
let formattedTemperature = String(format: "%.1f", data.temperature) // 小数点第二位以降切り捨て
Text("\(data.locationName)")
.font(.title)
Text("\(formattedTemperature)℃")
.font(.title)
Text(data.description)
.font(.headline)
}
}
Button {
viewModel.weatherData.removeAll()
viewModel.getWeatherData()
} label: {
Text("Refresh")
.font(.largeTitle)
}
}
.navigationTitle("Weather")
.onAppear {
viewModel.getWeatherData()
}
}
}
}
ViewModel (ビューモデル)
import SwiftUI
import CoreLocation
import Alamofire
import SwiftyJSON
class HomeViewModel: ObservableObject {
@Published var weatherData: [WeatherData] = []
private let location = CLLocation()
private let geocoder = CLGeocoder()
func getWeatherData() {
let apiKey = "<#発行したAPIキー#>"
let baseUrl = "https://api.openweathermap.org/data/2.5/weather?"
let units = "metric"
let count = 10
for _ in 0..<count {
let latitude = Double.random(in: -90...90) // ランダムな緯度
let longitude = Double.random(in: -180...180) // ランダムな経度
let url = "\(baseUrl)lat=\(latitude)&lon=\(longitude)&appid=\(apiKey)&units=\(units)"
// APIリクエストを行う
AF.request(url).responseJSON { response in
switch response.result {
case .success(let value):
// SwiftyJSONを使ってJSONをパースする
let json = JSON(value)
let temperature = json["main"]["temp"].doubleValue
let description = json["weather"][0]["description"].stringValue
// 位置情報から地名を取得する
self.geocoder.reverseGeocodeLocation(CLLocation(latitude: latitude, longitude: longitude)) { placemarks, error in
if let placemark = placemarks?.first {
let locationName = placemark.locality ?? placemark.name ?? "Unknown Location"
let data = WeatherData(temperature: temperature, description: description, locationName: locationName)
self.weatherData.append(data)
} else {
let data = WeatherData(temperature: temperature, description: description, locationName: "Unknown Location")
self.weatherData.append(data)
}
}
case .failure(let error):
print(error)
}
}
}
}
}