Weather implements the complete Dark Sky API for Swift Package Manager. It's fast and modular, leveraging Codable for serialization and URLSession for transport. Errors are concise and enumerated -- no mysteries or surprises. It works with Core Location out of the box.
It's the easiest way to add local (and localized) weather forecasts to any app on every Apple platform.
Included in the package
Targets iOS/iPadOS/tvOS 13, as well as watchOS 6 and macOS 10.15 Catalina. Written in Swift 5.4 using the Foundation and Core Location frameworks and requires Xcode 12.5 or newer to build. Command-line interface depends on Swift Argument Parser.
Weather requires a Dark Sky API key to function. If you already have a developer account with Dark Sky, the API remains available following acquisition by Apple. Sign-ups for new accounts are closed.
Forecast.Request holds the API key as a static property that can be set once during app launch, and doesn't need to be configured with each request:
import Foundation
import Weather
Forecast.Request.key = "268a49e46c1b588ede555c8b4cc034f4"Forecasts are available in 50+ languages. Check the API documentation for a complete, up-to-date list of supported languages.
By default, Weather requests forecasts in the current system language, defaulting to English if no matching translation is available. To request forecasts in a specific language, not the current system language, set a specific language code:
import Foundation
import Weather
Forecast.Request.language = .auto // Locale.current.language ?? .en
Forecast.Request.language = .auto(default: .es) // Locale.current.language ?? .es
Forecast.Request.language = .es // .esSame deal with selecting a units system for measurements; set it and forget it:
import Foundation
import Weather
Forecast.Request.units = .auto // .usAll measurements with an associated unit (temperature, speed, distance, pressure) are deserialized to convertible Measurement structs.
Forecast requests require a geographic location to construct a specific request instance. Optionally, use the Forecast.Block enumeration to customize which sections ("blocks") are included in returned forecasts. (All blocks are included by default.)
import Foundation
import CoreLocation
import Weather
let coordinate: CLLocationCoordinate2D = CLLocationCoordinate2D(latitude: 43.6616968, longitude: -70.1937586)
Forecast.request(Forecast.Request(coordinate: coordinate, blocks: [.current, .alerts])) { forecast, error in
guard let forecast: Forecast = forecast,
let temperature: Temperature = forecast.current?.temperature else {
print(error ?? .forecastNotAvailable)
return
}
let formatter: MeasurementFormatter = MeasurementFormatter()
formatter.unitOptions = .providedUnit
print(formatter.string(from: temperature.actual))
}Any forecast request becomes a time machine request by specifying a Date when constructing the request:
import Foundation
import CoreLocation
import Weather
let coordinate: CLLocationCoordinate2D = CLLocationCoordinate2D(latitude: 43.6616968, longitude: -70.1937586)
Forecast.request(Forecast.Request(coordinate: coordinate, date: Date(timeIntervalSince1970: 247156860.0))) { forecast, error in
...
}