Apple WeatherKit を使ってお天気 Mac アプリを作った
はじめに
WeatherKit 使って自分用にお天気情報アプリを作ったので、適当な備忘録になります。
ついでに SwiftUI / Combine も初めて。
梅雨時に作ったので・・・画面映えしない・・・。
準備編
- Apple の
Certificates, Identifiers & Profiles
Identifiers
->Capabilities
で WheatherKit を有効にする
-
Signing & Capabilities
でApp Sandbox
->Incoming Connections(Sever)
/Outgoing Connections(Cliet)
にチェック入れる(Mac アプリのみかも)
※ Location
にチェックしているのはアプリの方で現在地の天気を計測する機能を実装している為であり、必須ではありません
Apple DeveloprForm に投稿してくれてました。私もハマったので助かりました!
サンキュー海外ニキ!
実装編
実装は正直、ほとんどサンプル通りに作っただけですね・・・。
sample : https://developer.apple.com/documentation/weatherkit/fetching_weather_forecasts_with_weatherkit
一応コード書いておきます。
でも、サンプルの WeatherData
でいいと思う・・・。
@MainActor
final class WeatherRepository {
private let service = WeatherService.shared
@Published var currentWeather: CurrentWeather?
@Published var dailyForecasts: Forecast<DayWeather>?
@Published var hourlyForecasts: Forecast<HourWeather>?
@discardableResult
func weather(location: CLLocation) async -> CurrentWeather? {
let currentWeather = await Task.detached(priority: .userInitiated) {
let forcast = try? await self.service.weather(
for: location,
including: .current)
return forcast
}.value
self.currentWeather = currentWeather
return currentWeather
}
@discardableResult
func dailyForecast(location: CLLocation) async -> Forecast<DayWeather>? {
let dayWeather = await Task.detached(priority: .userInitiated) {
let forcast = try? await self.service.weather(
for: location,
including: .daily)
return forcast
}.value
self.dailyForecasts = dayWeather
return dayWeather
}
@discardableResult
func hourlyForecast(location: CLLocation) async -> Forecast<HourWeather>? {
let hourWeather = await Task.detached(priority: .userInitiated) {
let forcast = try? await self.service.weather(
for: location,
including: .hourly)
return forcast
}.value
self.hourlyForecasts = hourWeather
return hourWeather
}
}
weather function
CurrentWeather を取得できます。現在の天気情報ですね。
dailyForecast function
日次の天気情報を取得できます。
(今回は使ってないです)
hourlyForecast function
時間ごとの天気情報を取得できます。
まあ、実装はこれだけですね。あとは各 Publisher を sink しておけばいいです。
WeatherKit の実装自体はサンプル通りに作れば特に問題ないかと思います。
おまけ
天気の状態を表す WeatherCondition
はとても細かく状態を表してくれます。今回、私のアプリではもうちょっと大雑把でも良かったので、 Translator をかまして粒度を大きくしました。
それと Apple が提供する Weather のデータには isDaylight
というプロパティもあるので、これを使って昼夜みたいな分岐も用意しました。
// 自作アプリで使う Condition みたいな感じ.
enum WeatherType {
case fine
case fineNight
case partlyCloudy
case partlyCloudyNight
case rain
case cloudiness
case heavyRain
case snow
case heavySnow
case tropicalStorm
case thunderStorm
}
struct WeatherConditionTranslatorInput {
let condition: WeatherCondition
let isNight: Bool
}
struct WeatherConditionTranslator: Translator {
func translate(_ input: WeatherConditionTranslatorInput) -> WeatherType {
switch(input.condition) {
case .clear: return input.isNight ? .fineNight : .fine
case .mostlyClear: return input.isNight ? .fineNight : .fine
case .cloudy: return .cloudiness
case .mostlyCloudy: return .cloudiness
case .partlyCloudy: return input.isNight ? .partlyCloudyNight : .partlyCloudy
case .rain: return .rain
case .drizzle: return .rain
case .freezingDrizzle: return .snow
case .heavyRain: return .heavyRain
case .freezingRain: return .heavyRain
case .sleet: return .snow
case .snow: return .snow
case .blowingSnow: return .heavySnow
case .heavySnow: return .heavySnow
case .tropicalStorm: return .tropicalStorm
case .strongStorms: return .tropicalStorm
case .thunderstorms: return .thunderStorm
default: return .cloudiness
}
}
}
ご紹介
技術書典で Flutterで作るアプリとゲームの融合 〜電卓騎士の開発Tips〜 を公開しています。
この書籍は Flutter でのちょっと変わった電卓の Tips を色々記載しています。無料ですので良かったら DL してください。
アプリ自体も無料で公開しています。
Discussion