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.2 using the Foundation and Core Location frameworks and requires Xcode 11.4 or newer to build. Command-line interface depends on Swift Argument Parser.
Weather
requires a (free) Dark Sky API key* to function. 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"
*Sadly Dark Sky is no longer accepting new signups, though the API is still available if you already have an API key. For now anyway.
Forecasts are available in 50+ languages and growing. 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 // .es
Same deal with selecting a units system for measurements; set it and forget it:
import Foundation
import Weather
Forecast.Request.units = .auto // .us
All 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
...
}