weatherkit

weatherkit

熱門

取得 WeatherKit 的目前天氣、逐分鐘、每小時與每日預報;天氣警報;iOS 18+ 的天氣變化、歷史比較、摘要與統計資料;以及必要的 Apple Weather 來源標示。適用於整合天氣資料、顯示預報或警報、快取 WeatherKit 回應、顯示來源標示,或在 iOS App 中檢視 WeatherKit 查詢限制。

940星標
47分支
更新於 2026/7/15
SKILL.md
唯讀
名稱
weatherkit
描述

取得 WeatherKit 的目前天氣、逐分鐘、每小時與每日預報;天氣警報;iOS 18+ 的天氣變化、歷史比較、摘要與統計資料;以及必要的 Apple Weather 來源標示。適用於整合天氣資料、顯示預報或警報、快取 WeatherKit 回應、顯示來源標示,或在 iOS App 中檢視 WeatherKit 查詢限制。

WeatherKit

使用 WeatherService 取得目前天氣狀況、每小時與每日預報、天氣警報以及歷史統計資料。顯示必要的 Apple Weather 來源標示。

目錄

設定

專案設定

  1. 在 Xcode 中啟用 WeatherKit 功能(加入授權)
  2. 在 Apple Developer 入口網站為你的 App ID 啟用 WeatherKit
  3. 如果使用裝置位置,請在 Info.plist 中加入 NSLocationWhenInUseUsageDescription
  4. 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:它只暴露 alertAvailabilityminuteAvailability,而不是目前、每小時或每日天氣的廣泛可用性矩陣。

選擇性查詢

只取得你需要的資料集,以減少 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() 格式化以符合地區設定

參考資料