WeatherKit には二つの入口があります。一つはアプリ内から直接呼ぶ Swift の WeatherKit フレームワーク、もう一つはサーバーから叩く REST API です。Rork Max が生成するのはネイティブ Swift アプリですから、基本は前者を使います。
私の判断基準はこうです。予報をその場で表示するだけなら Swift API、複数アプリやバックエンドで天気データを共有・キャッシュするなら REST API、という分け方です。両者は同じ月間クォータ(無料枠は Apple Developer Program の範囲で月50万回)を共有するため、サーバー側で一度取得して配るほうが、呼び出し回数を抑えられる場面があります。私自身は、まず Swift API で素早く出し、共有が必要になった段階で REST へ移すことを推奨します。最初から作り込みすぎないほうが、結果的に手戻りが少ないと感じています。
今回は単一アプリなので Swift API を選びました。最小の取得コードはこうなります。
import WeatherKitimport CoreLocation@MainActorfinal class ForecastStore: ObservableObject { @Published var current: CurrentWeather? @Published var hourly: [HourWeather] = [] private let service = WeatherService.shared func load(for location: CLLocation) async { do { let weather = try await service.weather( for: location, including: .current, .hourly ) self.current = weather.0 self.hourly = Array(weather.1.forecast.prefix(24)) } catch { print("WeatherKit error: \(error.localizedDescription)") } }}
WeatherKit の Swift API は、API キーを直接コードに書きません。代わりに、Apple Developer のアカウントで WeatherKit を有効化し、アプリの Capability に追加することで認証が通ります。Rork Max が生成したプロジェクトをそのまま使う場合、ここが抜けやすい箇所です。実機で空データが返るというトラブルの多くは、コードではなくこの設定漏れが原因でした。
確認すべきは次の三点です。
Apple Developer の Identifiers で、アプリの App ID に WeatherKit が有効化されていること
プロジェクトの Signing & Capabilities に WeatherKit が追加されていること(Rork Max のクラウドビルドでも内部的に同じ設定が必要です)
struct CacheEntry { let location: CLLocation let fetchedAt: Date let current: CurrentWeather}func shouldRefetch(_ entry: CacheEntry?, for location: CLLocation) -> Bool { guard let entry else { return true } let age = Date().timeIntervalSince(entry.fetchedAt) let moved = entry.location.distance(from: location) // 15分以上経過、または2km以上移動したら再取得 return age > 900 || moved > 2000}