取得 WeatherKit 的目前天氣、逐分鐘、每小時與每日預報;天氣警報;iOS 18+ 的天氣變化、歷史比較、摘要與統計資料;以及必要的 Apple Weather 來源標示。適用於整合天氣資料、顯示預報或警報、快取 WeatherKit 回應、顯示來源標示,或在 iOS App 中檢視 WeatherKit 查詢限制。
WeatherKit
使用 WeatherService 取得目前天氣狀況、每小時與每日預報、天氣警報以及歷史統計資料。顯示必要的 Apple Weather 來源標示。
目錄
設定
專案設定
- 在 Xcode 中啟用 WeatherKit 功能(加入授權)
- 在 Apple Developer 入口網站為你的 App ID 啟用 WeatherKit
- 如果使用裝置位置,請在 Info.plist 中加入
NSLocationWhenInUseUsageDescription - WeatherKit 需要有效的 Apple Developer Program 會員資格
匯入
import WeatherKit
import CoreLocation
建立服務
使用共享的單例或建立實例。WeatherService 符合 Sendable;請將 App 快取與 UI 狀態分開隔離。
let weatherService = WeatherService.shared
// 或
let weatherService = WeatherService()
取得目前天氣
取得某個位置的目前天氣狀況。回傳一個包含所有可用資料集的 Weather 物件。
WeatherKit 的溫度是 Measurement<UnitTemperature> 值;使用 .formatted() 顯示,讓單位與數字格式遵循使用者的地區設定。
func fetchCurrentWeather(for location: CLLocation) async throws -> CurrentWeather {
let weather = try await weatherService.weather(for: location)
return weather.currentWeather
}
// 使用結果
func displayCurrent(_ current: CurrentWeather) {
let temp = current.temperature // Measurement<UnitTemperature>
let condition = current.condition // WeatherCondition 列舉
let symbol = current.symbolName // SF Symbol 名稱
let humidity = current.humidity // Double (0-1)
let wind = current.wind // Wind (速度、方向、陣風)
let uvIndex = current.uvIndex // UVIndex
print("\(condition): \(temp.formatted())")
}
預報
每小時預報
預設回傳從目前小時開始的連續 25 小時。
func fetchHourlyForecast(for location: CLLocation) async throws -> Forecast<HourWeather> {
let weather = try await weatherService.weather(for: location)
return weather.hourlyForecast
}
// 迭代每小時
for hour in hourlyForecast {
print("\(hour.date): \(hour.temperature.formatted()), \(hour.condition)")
}
每日預報
預設回傳從今天開始的連續 10 天。
func fetchDailyForecast(for location: CLLocation) async throws -> Forecast<DayWeather> {
let weather = try await weatherService.weather(for: location)
return weather.dailyForecast
}
// 迭代每天
for day in dailyForecast {
print("\(day.date): \(day.lowTemperature.formatted()) - \(day.highTemperature.formatted())")
print(" 狀況: \(day.condition), 降雨機率: \(day.precipitationChance)")
}
自訂日期範圍
使用 WeatherQuery 請求特定日期範圍的預報。
每日與每小時的日期範圍查詢使用包含的 startDate 與排除的 endDate。它們可以包含從 2021 年 8 月 1 日開始的歷史資料。預報最多可提供未來 10 天;每次請求最多回傳 10 天的每日預報或約 240 小時的每小時預報。
func fetchExtendedForecast(for location: CLLocation) async throws -> Forecast<DayWeather> {
let startDate = Date.now
let endDate = Calendar.current.date(byAdding: .day, value: 10, to: startDate)!
let forecast = try await weatherService.weather(
for: location,
including: .daily(startDate: startDate, endDate: endDate)
)
return forecast
}
若要取得明天的特定預報,請請求當地明天的日期區間,而不是使用逐分鐘預報:
func fetchTomorrowForecast(for location: CLLocation) async throws -> Forecast<DayWeather> {
let calendar = Calendar.current
let tomorrow = calendar.startOfDay(
for: calendar.date(byAdding: .day, value: 1, to: .now)!
)
let dayAfterTomorrow = calendar.date(byAdding: .day, value: 1, to: tomorrow)!
return try await weatherService.weather(
for: location,
including: .daily(startDate: tomorrow, endDate: dayAfterTomorrow)
)
}
天氣警報
取得某個位置的活躍天氣警報。警報包含嚴重性、摘要與受影響區域。
func fetchAlerts(for location: CLLocation) async throws -> [WeatherAlert]? {
let weather = try await weatherService.weather(for: location)
return weather.weatherAlerts
}
// 處理警報
if let alerts = weatherAlerts {
for alert in alerts {
print("警報: \(alert.summary)")
print("嚴重性: \(alert.severity)")
print("區域: \(alert.region ?? "未知區域")")
print("詳細資訊: \(alert.detailsURL)") // 非可選,且為來源標示所需
}
}
對於警報儀表板,在討論支援檢查時請明確命名 WeatherAvailability:它只暴露 alertAvailability 與 minuteAvailability,而不是目前、每小時或每日天氣的廣泛可用性矩陣。
選擇性查詢
只取得你需要的資料集,以減少 API 用量與回應大小。每個 WeatherQuery 類型對應一個資料集。
單一資料集
let current = try await weatherService.weather(
for: location,
including: .current
)
// current 是 CurrentWeather
多個資料集
let (current, hourly, daily) = try await weatherService.weather(
for: location,
including: .current, .hourly, .daily
)
// current: CurrentWeather, hourly: Forecast<HourWeather>, daily: Forecast<DayWeather>
逐分鐘預報
僅限部分地區。回傳未來一小時以分鐘為粒度的降雨預報。
let minuteForecast = try await weatherService.weather(
for: location,
including: .minute
)
// minuteForecast: Forecast<MinuteWeather>? (若不可用則為 nil)
可用的查詢類型
| 查詢 | 回傳類型 | 說明 |
|---|---|---|
.current |
CurrentWeather |
目前觀測狀況 |
.hourly |
Forecast<HourWeather> |
從目前小時起 25 小時 |
.daily |
Forecast<DayWeather> |
從今天起 10 天 |
.minute |
Forecast<MinuteWeather>? |
下一小時降雨(限部分地區) |
.alerts |
[WeatherAlert]? |
活躍天氣警報 |
.availability |
WeatherAvailability |
僅警報與逐分鐘預報可用性 |
.changes |
WeatherChanges? |
即將到來的顯著天氣變化(iOS 18+) |
.historicalComparisons |
HistoricalComparisons? |
目前天氣與歷史平均值的比較(iOS 18+) |
情境查詢
對於 iOS 18+ 的「明天是否異常」或「有什麼變化」功能,請同時請求可選的 .changes 與 .historicalComparisons 結果:前者報告即將到來的顯著變化,後者提供歷史背景。
let (changes, comparisons) = try await weatherService.weather(
for: location,
including: .changes, .historicalComparisons
)
歷史摘要與統計資料使用 WeatherService 方法而非 WeatherQuery。請載入 references/weatherkit-patterns.md 以了解其元組順序、API 與統計資料專用屬性。
來源標示
Apple 要求使用 WeatherKit 的 App 必須顯示來源標示。這是法律要求。
取得來源標示
func fetchAttribution() async throws -> WeatherAttribution {
return try await weatherService.attribution
}
請載入 references/weatherkit-patterns.md 以取得完整的 SwiftUI 來源標示檢視與快取整合。
來源標示屬性
| 屬性 | 用途 |
|---|---|
combinedMarkLightURL |
淺色背景用的 Apple Weather 標誌 |
combinedMarkDarkURL |
深色背景用的 Apple Weather 標誌 |
squareMarkURL |
方形 Apple Weather 標誌 |
legalPageURL |
法律來源標示網頁的 URL |
legalAttributionText |
當無法顯示網頁時的文字替代方案 |
serviceName |
天氣資料提供者名稱 |
可用性
檢查某個位置的天氣警報或逐分鐘預報資料是否可用。WeatherAvailability 僅回報警報與逐分鐘可用性;其他資料集(例如目前天氣)預期對地理位置都有支援。
func checkAvailability(for location: CLLocation) async throws {
let availability = try await weatherService.weather(
for: location,
including: .availability
)
// 檢查特定資料集可用性
if availability.alertAvailability == .available {
// 可以安全取得警報
}
if availability.minuteAvailability == .available {
// 該地區有逐分鐘預報
}
}
常見錯誤
不要:未顯示 Apple Weather 來源標示就上架
在顯示 WeatherKit 資料的任何地方,顯示適當的 Apple Weather 標誌並連結 legalPageURL;只有在無法顯示法律頁面時才使用 legalAttributionText。
不要:只需要目前天氣卻取得所有資料集
每個資料集查詢都會計入你的 API 配額。請使用選擇性查詢中顯示的選擇性查詢,只取得 UI 顯示所需的資料。
不要:忽略逐分鐘預報的不可用性
在不支援的地區,逐分鐘預報是可選的。請檢查可用性並處理 nil 結果,而不是強制解開。
不要:忘記 WeatherKit 授權
如果未啟用該功能,WeatherService 呼叫會在執行時拋出錯誤。
// 錯誤:未設定 WeatherKit 功能
let weather = try await weatherService.weather(for: location) // 拋出錯誤
// 正確:在 Xcode 的 Signing & Capabilities 中啟用 WeatherKit
// 並在 Apple Developer 入口網站為你的 App ID 啟用
不要:重複請求而不快取
WeatherKit 模型包含 metadata.expirationDate。請將回應快取到該到期時間,而不是自行設定固定間隔或在每次檢視出現時重新取得。讓模型或快取擁有 loadIfNeeded;完整的 actor 模式請參考 references/weatherkit-patterns.md。
審查清單
- [ ] 在 Xcode 與 Apple Developer 入口網站啟用 WeatherKit 功能
- [ ] 有效的 Apple Developer Program 會員資格(WeatherKit 必要)
- [ ] 在顯示天氣資料的任何地方顯示 Apple Weather 來源標示
- [ ] 來源標示標誌使用正確的配色方案(淺色/深色)
- [ ] 連結法律來源標示頁面或顯示
legalAttributionText - [ ] 只取得所需的
WeatherQuery資料集(不需要時不要使用完整的weather(for:)) - [ ] 逐分鐘預報視為可選(在不支援的地區為 nil)
- [ ] 天氣警報在迭代前檢查是否為 nil
- [ ] 警報詳細資訊連結使用非可選的
detailsURL;可選的region需安全處理 nil - [ ] 回應快取到每個模型的
metadata.expirationDate - [ ]
WeatherAvailability用於警報/逐分鐘可用性,而非作為廣泛支援矩陣 - [ ] 在傳遞
CLLocation給服務前,先請求位置權限 - [ ] 溫度與測量值使用
Measurement.formatted()格式化以符合地區設定
參考資料
- 進階模式(SwiftUI 儀表板、圖表整合、歷史統計資料):references/weatherkit-patterns.md
- WeatherKit 框架
- WeatherService
- WeatherAttribution
- WeatherQuery
- WeatherQuery.daily(startDate:endDate:)
- WeatherQuery.hourly(startDate:endDate:)
- CurrentWeather
- CurrentWeather.temperature
- Measurement.formatted()
- Forecast
- HourWeather
- DayWeather
- WeatherAlert
- WeatherAvailability
- WeatherMetadata.expirationDate
- WeatherQuery.changes
- WeatherQuery.historicalComparisons
- WeatherKit 更新
- 為今天的天氣帶來背景資訊
- 使用 WeatherKit 取得天氣預報




