weatherkit
Fetch current, hourly, and daily weather forecasts and display required attribution using WeatherKit. Use when integrating weather data, showing forecasts, handling weather alerts, displaying Apple Weather attribution, or querying historical weather statistics in iOS apps.
What this skill does
# WeatherKit
Fetch current conditions, hourly and daily forecasts, weather alerts, and
historical statistics using `WeatherService`. Display required Apple Weather
attribution. Targets Swift 6.3 / iOS 26+.
## Contents
- [Setup](#setup)
- [Fetching Current Weather](#fetching-current-weather)
- [Forecasts](#forecasts)
- [Weather Alerts](#weather-alerts)
- [Selective Queries](#selective-queries)
- [Attribution](#attribution)
- [Availability](#availability)
- [Common Mistakes](#common-mistakes)
- [Review Checklist](#review-checklist)
- [References](#references)
## Setup
### Project Configuration
1. Enable the **WeatherKit** capability in Xcode (adds the entitlement)
2. Enable WeatherKit for your App ID in the Apple Developer portal
3. Add `NSLocationWhenInUseUsageDescription` to Info.plist if using device location
4. WeatherKit requires an active Apple Developer Program membership
### Import
```swift
import WeatherKit
import CoreLocation
```
### Creating the Service
Use the shared singleton or create an instance. The service is `Sendable` and
thread-safe.
```swift
let weatherService = WeatherService.shared
// or
let weatherService = WeatherService()
```
## Fetching Current Weather
Fetch current conditions for a location. Returns a `Weather` object with all
available datasets.
```swift
func fetchCurrentWeather(for location: CLLocation) async throws -> CurrentWeather {
let weather = try await weatherService.weather(for: location)
return weather.currentWeather
}
// Using the result
func displayCurrent(_ current: CurrentWeather) {
let temp = current.temperature // Measurement<UnitTemperature>
let condition = current.condition // WeatherCondition enum
let symbol = current.symbolName // SF Symbol name
let humidity = current.humidity // Double (0-1)
let wind = current.wind // Wind (speed, direction, gust)
let uvIndex = current.uvIndex // UVIndex
print("\(condition): \(temp.formatted())")
}
```
## Forecasts
### Hourly Forecast
Returns 25 contiguous hours starting from the current hour by default.
```swift
func fetchHourlyForecast(for location: CLLocation) async throws -> Forecast<HourWeather> {
let weather = try await weatherService.weather(for: location)
return weather.hourlyForecast
}
// Iterate hours
for hour in hourlyForecast {
print("\(hour.date): \(hour.temperature.formatted()), \(hour.condition)")
}
```
### Daily Forecast
Returns 10 contiguous days starting from the current day by default.
```swift
func fetchDailyForecast(for location: CLLocation) async throws -> Forecast<DayWeather> {
let weather = try await weatherService.weather(for: location)
return weather.dailyForecast
}
// Iterate days
for day in dailyForecast {
print("\(day.date): \(day.lowTemperature.formatted()) - \(day.highTemperature.formatted())")
print(" Condition: \(day.condition), Precipitation: \(day.precipitationChance)")
}
```
### Custom Date Range
Request forecasts for specific date ranges using `WeatherQuery`.
```swift
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
}
```
## Weather Alerts
Fetch active weather alerts for a location. Alerts include severity, summary,
and affected regions.
```swift
func fetchAlerts(for location: CLLocation) async throws -> [WeatherAlert]? {
let weather = try await weatherService.weather(for: location)
return weather.weatherAlerts
}
// Process alerts
if let alerts = weatherAlerts {
for alert in alerts {
print("Alert: \(alert.summary)")
print("Severity: \(alert.severity)")
print("Region: \(alert.region)")
if let detailsURL = alert.detailsURL {
// Link to full alert details
}
}
}
```
## Selective Queries
Fetch only the datasets you need to minimize API usage and response size. Each
`WeatherQuery` type maps to one dataset.
### Single Dataset
```swift
let current = try await weatherService.weather(
for: location,
including: .current
)
// current is CurrentWeather
```
### Multiple Datasets
```swift
let (current, hourly, daily) = try await weatherService.weather(
for: location,
including: .current, .hourly, .daily
)
// current: CurrentWeather, hourly: Forecast<HourWeather>, daily: Forecast<DayWeather>
```
### Minute Forecast
Available in limited regions. Returns precipitation forecasts at minute
granularity for the next hour.
```swift
let minuteForecast = try await weatherService.weather(
for: location,
including: .minute
)
// minuteForecast: Forecast<MinuteWeather>? (nil if unavailable)
```
### Available Query Types
| Query | Return Type | Description |
|---|---|---|
| `.current` | `CurrentWeather` | Current observed conditions |
| `.hourly` | `Forecast<HourWeather>` | 25 hours from current hour |
| `.daily` | `Forecast<DayWeather>` | 10 days from today |
| `.minute` | `Forecast<MinuteWeather>?` | Next-hour precipitation (limited regions) |
| `.alerts` | `[WeatherAlert]?` | Active weather alerts |
| `.availability` | `WeatherAvailability` | Dataset availability for location |
## Attribution
Apple requires apps using WeatherKit to display attribution. This is a
legal requirement.
### Fetching Attribution
```swift
func fetchAttribution() async throws -> WeatherAttribution {
return try await weatherService.attribution
}
```
### Displaying Attribution in SwiftUI
```swift
import SwiftUI
import WeatherKit
struct WeatherAttributionView: View {
let attribution: WeatherAttribution
@Environment(\.colorScheme) private var colorScheme
var body: some View {
VStack {
// Display the Apple Weather mark
AsyncImage(url: markURL) { image in
image
.resizable()
.scaledToFit()
.frame(height: 20)
} placeholder: {
EmptyView()
}
// Link to the legal attribution page
Link("Weather data sources", destination: attribution.legalPageURL)
.font(.caption2)
.foregroundStyle(.secondary)
}
}
private var markURL: URL {
colorScheme == .dark
? attribution.combinedMarkDarkURL
: attribution.combinedMarkLightURL
}
}
```
### Attribution Properties
| Property | Use |
|---|---|
| `combinedMarkLightURL` | Apple Weather mark for light backgrounds |
| `combinedMarkDarkURL` | Apple Weather mark for dark backgrounds |
| `squareMarkURL` | Square Apple Weather logo |
| `legalPageURL` | URL to the legal attribution web page |
| `legalAttributionText` | Text alternative when a web view is not feasible |
| `serviceName` | Weather data provider name |
## Availability
Check which weather datasets are available for a given location. Not all datasets
are available in all countries.
```swift
func checkAvailability(for location: CLLocation) async throws {
let availability = try await weatherService.weather(
for: location,
including: .availability
)
// Check specific dataset availability
if availability.alertAvailability == .available {
// Safe to fetch alerts
}
if availability.minuteAvailability == .available {
// Minute forecast available for this region
}
}
```
## Common Mistakes
### DON'T: Ship without Apple Weather attribution
Omitting attribution violates the WeatherKit terms of service and risks App Review
rejection.
```swift
// WRONG: Show weather data without attribution
VStack {
Text("72F, Sunny")
}
// CORRECT: Always include attribution
VStack {
Text("72F, Sunny")
WeatherAttributionView(attribution: attribution)
}
```
### DRelated in General
modeling-omnistudio-epc-catalog
IncludedSalesforce Industries CME EPC product-modeling skill for Product2-based catalog creation. Use when creating EPC products, configuring product attributes, building offer bundles with Product Child Items, or reviewing EPC DataPack JSON metadata for product catalog changes. TRIGGER when: user creates or updates Product2 EPC records, AttributeAssignment payloads, AttributeMetadata/AttributeDefaultValues, Offer bundles, or ProductChildItem relationships. DO NOT TRIGGER when: designing OmniScripts/FlexCards/Integration Procedures (use building-omnistudio-omniscript, building-omnistudio-flexcard, or building-omnistudio-integration-procedure), implementing Apex business logic (use generating-apex), or troubleshooting deployment pipelines (use deploying-metadata).
relationship-science-coach
IncludedUse this skill for direct, practical adult relationship coaching: couples conflict, repair, trust, marriage, dating, flirting, attachment patterns, emotional connection, sex, desire differences, eroticism, kink negotiation, affection, love languages, breakups, and long-term passion. Draw on Gottman, EFT and Hold Me Tight, attachment science, modern sex research, Perel, Nagoski, Kerner, Schnarch, Love and Stosny, and flexible love-language tools. Be concrete and low-hedge. Redirect only for imminent danger, abuse, coercive control, minors, non-consent, self-harm, stalking, or medical/legal/psychiatric decisions.
building-sf-integrations
IncludedSalesforce integration architecture and runtime plumbing with 120-point scoring. Use this skill to set up Named Credentials, External Credentials, External Services, REST/SOAP callout patterns, Platform Events, and Change Data Capture. TRIGGER when: user sets up Named Credentials, External Services, REST/SOAP callouts, Platform Events, CDC, or touches .namedCredential-meta.xml files. DO NOT TRIGGER when: Connected App/OAuth config (use configuring-connected-apps), Apex-only logic (use generating-apex), or data import/export (use handling-sf-data).
venue-templates
IncludedAccess comprehensive LaTeX templates, formatting requirements, and submission guidelines for major scientific publication venues (Nature, Science, PLOS, IEEE, ACM), academic conferences (NeurIPS, ICML, CVPR, CHI), research posters, and grant proposals (NSF, NIH, DOE, DARPA). This skill should be used when preparing manuscripts for journal submission, conference papers, research posters, or grant proposals and need venue-specific formatting requirements and templates.
let-fate-decide
IncludedDraws the 12 Houses of the Zodiac Tarot spread to inject entropy into planning when prompts are vague, ambiguous, or casually delegated. Interprets the spread to guide next steps. Use when the user says 'let fate decide', 'YOLO', 'whatever', 'idk', or other nonchalant phrases, makes Yu-Gi-Oh references, or when you are about to arbitrarily pick between multiple reasonable approaches. Prefer over ask-questions-if-underspecified when the user's tone is casual or playful rather than precision-seeking.
net-ops
IncludedCross-platform network troubleshooting (Windows, macOS, Linux) via local or remote shell. Use for: DNS broken, can't resolve hostnames, nslookup/dig works but apps fail, NRPT, WFP, scutil, /etc/resolver, systemd-resolved, /etc/resolv.conf, NetworkManager, VPN DNS leak residue (ProtonVPN/Mullvad/WireGuard/AnyConnect), AV/firewall blocking DNS or DoH, Tailscale DNS interaction, intermittent connectivity, remote diagnostics over SSH.