diff --git a/.github/workflows/swift.yml b/.github/workflows/swift.yml
index a8f4bf0..08e9469 100644
--- a/.github/workflows/swift.yml
+++ b/.github/workflows/swift.yml
@@ -23,4 +23,4 @@ jobs:
env:
API_KEY: ${{ secrets.API_KEY }}
- name: Codecov
- uses: codecov/codecov-action@v1.0.15
\ No newline at end of file
+ uses: codecov/codecov-action@v2
\ No newline at end of file
diff --git a/.vscode/launch.json b/.vscode/launch.json
new file mode 100644
index 0000000..b7e1bb4
--- /dev/null
+++ b/.vscode/launch.json
@@ -0,0 +1,15 @@
+{
+ "configurations": [
+ {
+ "type": "lldb",
+ "request": "launch",
+ "name": "Test HPOpenWeather",
+ "program": "/Applications/Xcode.app/Contents/Developer/usr/bin/xctest",
+ "args": [
+ ".build/debug/HPOpenWeatherPackageTests.xctest"
+ ],
+ "cwd": "${workspaceFolder:HPOpenWeather}",
+ "preLaunchTask": "swift: Build All"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/HPOpenWeather.podspec b/HPOpenWeather.podspec
index a44214c..e1044ce 100644
--- a/HPOpenWeather.podspec
+++ b/HPOpenWeather.podspec
@@ -1,7 +1,7 @@
Pod::Spec.new do |s|
s.name = "HPOpenWeather"
- s.version = "4.1.5"
+ s.version = "5.0.0"
s.summary = "Cross-platform framework to communicate with the OpenWeatherMap JSON API"
s.license = { :type => "MIT", :file => "LICENSE.md" }
@@ -10,23 +10,23 @@ Pod::Spec.new do |s|
s.author = { "henrik-dmg" => "henrik@panhans.dev" }
s.social_media_url = "https://twitter.com/henrik_dmg"
- s.ios.deployment_target = "9.0"
- s.osx.deployment_target = "10.11"
- s.watchos.deployment_target = "3.0"
- s.tvos.deployment_target = "9.0"
+ s.ios.deployment_target = "13.0"
+ s.watchos.deployment_target = "7.0"
+ s.tvos.deployment_target = "13.0"
+ s.osx.deployment_target = "10.15"
s.source = { :git => 'https://github.com/henrik-dmg/HPOpenWeather.git', :tag => s.version }
s.source_files = "Sources/**/*.swift"
-
+
s.framework = "Foundation"
s.ios.framework = "UIKit"
s.watchos.framework = "UIKit"
s.tvos.framework = "UIKit"
- s.osx.framework = "AppKit"
- s.swift_version = "5.1"
+ s.swift_version = "5.5"
s.requires_arc = true
- s.dependency "HPNetwork"
+ s.dependency "HPNetwork", "~> 3.1.1"
+ s.dependency "HPURLBuilder", "~> 1.0.0"
end
diff --git a/Package.resolved b/Package.resolved
index 64216c5..e8836d1 100644
--- a/Package.resolved
+++ b/Package.resolved
@@ -6,8 +6,17 @@
"repositoryURL": "https://github.com/henrik-dmg/HPNetwork",
"state": {
"branch": null,
- "revision": "7e888cdaabf7cb6e8c6640db57cb4325099f79b2",
- "version": "2.0.2"
+ "revision": "2bdaaa3f1c9d52a30e5afb8f737c3b72f5afba0c",
+ "version": "3.1.1"
+ }
+ },
+ {
+ "package": "HPURLBuilder",
+ "repositoryURL": "https://github.com/henrik-dmg/HPURLBuilder",
+ "state": {
+ "branch": null,
+ "revision": "49ad1fb6f10914e7134dc9f8e5c21f48a52e3d37",
+ "version": "1.1.0"
}
}
]
diff --git a/Package.swift b/Package.swift
index 6ff0492..2161b65 100644
--- a/Package.swift
+++ b/Package.swift
@@ -1,4 +1,4 @@
-// swift-tools-version:5.1
+// swift-tools-version:5.5
// The swift-tools-version declares the minimum version of Swift required to build this package.
import PackageDescription
@@ -6,7 +6,7 @@ import PackageDescription
let package = Package(
name: "HPOpenWeather",
platforms: [
- .iOS(.v9), .macOS(.v10_11), .tvOS(.v9), .watchOS(.v3)
+ .iOS(.v13), .tvOS(.v13), .watchOS(.v7), .macOS(.v10_15)
],
products: [
// Products define the executables and libraries produced by a package, and make them visible to other packages.
@@ -17,14 +17,15 @@ let package = Package(
],
dependencies: [
// Dependencies declare other packages that this package depends on.
- .package(url: "https://github.com/henrik-dmg/HPNetwork", from: "2.0.0")
+ .package(url: "https://github.com/henrik-dmg/HPNetwork", from: "3.0.0"),
+ .package(url: "https://github.com/henrik-dmg/HPURLBuilder", from: "1.0.0")
],
targets: [
// Targets are the basic building blocks of a package. A target can define a module or a test suite.
// Targets can depend on other targets in this package, and on products in packages which this package depends on.
.target(
name: "HPOpenWeather",
- dependencies: ["HPNetwork"]
+ dependencies: ["HPNetwork", "HPURLBuilder"]
),
.testTarget(
name: "HPOpenWeatherTests",
diff --git a/README.md b/README.md
index cd2714c..4dd798e 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,4 @@
-
-
-
+# HPOpenWeather
@@ -8,21 +6,23 @@
[![GitHub license](https://img.shields.io/github/license/henrik-dmg/HPOpenWeather)](https://github.com/henrik-dmg/HPOpenWeather/blob/master/LICENSE.md)
HPOpenWeather is a cross-platform Swift framework to communicate with the OpenWeather One-Call API. See their [documentation](https://openweathermap.org/api/one-call-api) for further details.
+
## Installation
-HPOpenWeather supports iOS 9.0+, watchOS 3.0+, tvOS 9.0+ and macOS 10.10+.
+HPOpenWeather supports iOS 13.0+, watchOS 7.0+, tvOS 13.0+ and macOS 10.15+.
-#### SPM
+### SPM
-Add `.package(url: "https://github.com/henrik-dmg/HPOpenWeather", from: "4.0.0")` to your `Package.swift` file
+Add `.package(url: "https://github.com/henrik-dmg/HPOpenWeather", from: "5.0.0")` to your `Package.swift` file
-#### CocoaPods
+### CocoaPods
Add `pod 'HPOpenWeather'` to your `Podfile` and run `pod install`
## Usage
To get started, you need an API key from [OpenWeather](https://openweathermap.org). Put this API key in the initialiser, additionally you can also specify a custom temperature format and/or language used in the responses (see list for available languages and units below).
+
```swift
import HPOpenWeather
@@ -35,9 +35,10 @@ OpenWeather.shared.units = .metric
let settings = OpenWeather.Settings(apiKey: "yourAPIKey", language: .german, units: .metric)
OpenWeather.shared.apply(settings)
```
+
You can also customise the response data units and language by accessing the `language` and `units` propertis.
-## Making a request
+### Making a request
To make a request, initialize a new request object like this
@@ -53,10 +54,11 @@ let timemachineRequest = WeatherRequest(coordinate: .init(latitude: 40, longitud
**Note:** the date has to be at least 6 hours in the past
-To post a request, call `sendWeatherRequest` on `OpenWeather`:
+To post a request, call `sendWeatherRequest` on `OpenWeather`:
```swift
-OpenWeather.shared.performWeatherRequest(request) { result in
+// Classic completion handler approach
+OpenWeather.shared.schedule(request) { result in
switch result {
case .success(let response):
// do something with weather data here
@@ -64,11 +66,14 @@ OpenWeather.shared.performWeatherRequest(request) { result in
// handle error
}
}
+
+// Or using the new concurrency features
+let response = try await OpenWeather.shared.weatherResponse(request)
```
-**The following response languages are available**
+### Available languages (default in bold)
-- English (default)
+- **English**
- Russian
- Italian
- Spanish
@@ -88,8 +93,8 @@ OpenWeather.shared.performWeatherRequest(request) { result in
- Croatian
- Catalan
-**The following temperature units are available**
+### Available units (default in bold)
-- Celsius (default)
-- Kelvin
-- Fahrenheit
+- **Metric** (wind speed in m/s, temperature in Celsius)
+- Imperial (wind speed in mph, temperature in Fahrenheit)
+- Standard (wind speed in m/s, temperature in Kelvin)
diff --git a/Sources/HPOpenWeather/DataTypes/Alert.swift b/Sources/HPOpenWeather/DataTypes/Alert.swift
deleted file mode 100644
index 426a519..0000000
--- a/Sources/HPOpenWeather/DataTypes/Alert.swift
+++ /dev/null
@@ -1,25 +0,0 @@
-import Foundation
-
-/// Type that holds information about weather alerts
-public struct Alert: Codable, Hashable, Equatable {
-
- /// Name of the alert source. Please read here the full list of alert sources
- public let senderName: String
- /// Alert event name
- public let eventName: String
- //// Date and time of the start of the alert
- public let startDate: Date
- //// Date and time of the end of the alert
- public let endDate: Date
- /// Description of the alert
- public let description: String
-
- enum CodingKeys: String, CodingKey {
- case senderName = "sender_name"
- case eventName = "event"
- case startDate = "start"
- case endDate = "end"
- case description
- }
-
-}
diff --git a/Sources/HPOpenWeather/DataTypes/Forecasts/CurrentWeather.swift b/Sources/HPOpenWeather/DataTypes/Forecasts/CurrentWeather.swift
deleted file mode 100644
index 34694ae..0000000
--- a/Sources/HPOpenWeather/DataTypes/Forecasts/CurrentWeather.swift
+++ /dev/null
@@ -1,75 +0,0 @@
-import Foundation
-
-public struct CurrentWeather: BasicWeatherResponse, SunResponse {
-
- // MARK: - Coding Keys
-
- enum CodingKeys: String, CodingKey {
- case feelsLikeTemperature = "feels_like"
- case snow
- case rain
- case timestamp = "dt"
- case actualTemperature = "temp"
- case pressure
- case humidity
- case dewPoint = "dew_point"
- case uvIndex = "uvi"
- case cloudCoverage = "clouds"
- case visibility
- case windSpeed = "wind_speed"
- case windGust = "wind_gust"
- case windDirection = "wind_deg"
- case weatherArray = "weather"
- case sunrise
- case sunset
- }
-
- // MARK: - Properties
-
- public let timestamp: Date
- public let pressure: Double?
- public let humidity: Double?
- public let dewPoint: Double?
- public let uvIndex: Double?
- public let visibility: Double?
- public let cloudCoverage: Double?
- public let rain: Precipitation?
- public let snow: Precipitation?
-
- // Temperature
-
- private let actualTemperature: Double
- private let feelsLikeTemperature: Double
-
- public var temperature: Temperature {
- Temperature(actual: actualTemperature, feelsLike: feelsLikeTemperature)
- }
-
- // Weather Conditions
-
- private let weatherArray: [WeatherCondition]
-
- public var condition: WeatherCondition? {
- weatherArray.first
- }
-
- // Wind
-
- private let windSpeed: Double?
- private let windGust: Double?
- private let windDirection: Double?
-
- public var wind: Wind {
- Wind(speed: windSpeed, gust: windGust, degrees: windDirection)
- }
-
- // Sun
-
- private let sunrise: Date
- private let sunset: Date
-
- public var sun: Sun {
- Sun(sunset: sunset, sunrise: sunrise)
- }
-
-}
diff --git a/Sources/HPOpenWeather/DataTypes/Forecasts/DailyForecast.swift b/Sources/HPOpenWeather/DataTypes/Forecasts/DailyForecast.swift
deleted file mode 100644
index f466dab..0000000
--- a/Sources/HPOpenWeather/DataTypes/Forecasts/DailyForecast.swift
+++ /dev/null
@@ -1,70 +0,0 @@
-import Foundation
-
-public struct DailyForecast: BasicWeatherResponse, SunResponse {
-
- // MARK: - Coding Keys
-
- enum CodingKeys: String, CodingKey {
- case feelsLikeTemperature = "feels_like"
- case totalRain = "rain"
- case totalSnow = "snow"
- case timestamp = "dt"
- case temperature = "temp"
- case pressure
- case humidity
- case dewPoint = "dew_point"
- case uvIndex = "uvi"
- case cloudCoverage = "clouds"
- case visibility
- case windSpeed = "wind_speed"
- case windGust = "wind_gust"
- case windDirection = "wind_deg"
- case weatherArray = "weather"
- case sunrise
- case sunset
- }
-
- // MARK: - Properties
-
- public let temperature: DailyTemperature
- public let feelsLikeTemperature: DailyTemperature
- public let totalRain: Double?
- public let totalSnow: Double?
-
- public let timestamp: Date
- public let pressure: Double?
- public let humidity: Double?
- public let dewPoint: Double?
- public let uvIndex: Double?
- public let visibility: Double?
- public let cloudCoverage: Double?
-
- // Weather Conditions
-
- private let weatherArray: [WeatherCondition]
-
- public var condition: WeatherCondition? {
- weatherArray.first
- }
-
- // Wind
-
- private let windSpeed: Double?
- private let windGust: Double?
- private let windDirection: Double?
-
- public var wind: Wind {
- Wind(speed: windSpeed, gust: windGust, degrees: windDirection)
- }
-
- // Sun
-
- private let sunrise: Date
- private let sunset: Date
-
- public var sun: Sun {
- Sun(sunset: sunset, sunrise: sunrise)
- }
-
-}
-
diff --git a/Sources/HPOpenWeather/DataTypes/Forecasts/HourlyForecast.swift b/Sources/HPOpenWeather/DataTypes/Forecasts/HourlyForecast.swift
deleted file mode 100644
index 62febc2..0000000
--- a/Sources/HPOpenWeather/DataTypes/Forecasts/HourlyForecast.swift
+++ /dev/null
@@ -1,64 +0,0 @@
-import Foundation
-
-public struct HourlyForecast: BasicWeatherResponse {
-
- // MARK: - Coding Keys
-
- enum CodingKeys: String, CodingKey {
- case actualTemperature = "temp"
- case feelsLikeTemperature = "feels_like"
- case snow
- case rain
- case timestamp = "dt"
- case pressure
- case humidity
- case dewPoint = "dew_point"
- case uvIndex = "uvi"
- case cloudCoverage = "clouds"
- case visibility
- case windSpeed = "wind_speed"
- case windGust = "wind_gust"
- case windDirection = "wind_deg"
- case weatherArray = "weather"
- }
-
- // MARK: - Properties
-
- public let timestamp: Date
- public let pressure: Double?
- public let humidity: Double?
- public let dewPoint: Double?
- public let uvIndex: Double?
- public let visibility: Double?
- public let cloudCoverage: Double?
- public let rain: Precipitation?
- public let snow: Precipitation?
-
- // Temperature
-
- private let actualTemperature: Double
- private let feelsLikeTemperature: Double
-
- public var temperature: Temperature {
- Temperature(actual: actualTemperature, feelsLike: feelsLikeTemperature)
- }
-
- // Wind
-
- private let windSpeed: Double?
- private let windGust: Double?
- private let windDirection: Double?
-
- public var wind: Wind {
- Wind(speed: windSpeed, gust: windGust, degrees: windDirection)
- }
-
- // Weather
-
- private let weatherArray: [WeatherCondition]
-
- public var weather: [WeatherCondition] {
- weatherArray
- }
-
-}
diff --git a/Sources/HPOpenWeather/DataTypes/Precipitation.swift b/Sources/HPOpenWeather/DataTypes/Precipitation.swift
deleted file mode 100644
index d40ee0f..0000000
--- a/Sources/HPOpenWeather/DataTypes/Precipitation.swift
+++ /dev/null
@@ -1,16 +0,0 @@
-import Foundation
-
-/// Type that holds information about recent precipitation
-public struct Precipitation: Codable, Equatable, Hashable {
-
- /// Precipitation volume for the last 1 hour, measured in mm
- public var lastHour: Double?
- /// Precipitation volume for the last 3 hours, measured in mm
- public var lastThreeHours: Double?
-
- enum CodingKeys: String, CodingKey {
- case lastHour = "1h"
- case lastThreeHours = "3h"
- }
-
-}
diff --git a/Sources/HPOpenWeather/DataTypes/Temperature.swift b/Sources/HPOpenWeather/DataTypes/Temperature.swift
deleted file mode 100644
index 63686bd..0000000
--- a/Sources/HPOpenWeather/DataTypes/Temperature.swift
+++ /dev/null
@@ -1,11 +0,0 @@
-import Foundation
-
-/// Type that holds information about daily temperature changes
-public struct Temperature: Codable, Equatable, Hashable {
-
- /// The actually measured temperature
- public let actual: Double
- /// The feels-like temperature
- public let feelsLike: Double
-
-}
diff --git a/Sources/HPOpenWeather/DataTypes/WeatherIcon.swift b/Sources/HPOpenWeather/DataTypes/WeatherIcon.swift
deleted file mode 100644
index c327a75..0000000
--- a/Sources/HPOpenWeather/DataTypes/WeatherIcon.swift
+++ /dev/null
@@ -1,96 +0,0 @@
-#if canImport(UIKit)
-import UIKit
-#elseif canImport(AppKit)
-import AppKit
-#endif
-import Foundation
-
-public enum WeatherIcon: String, Codable, CaseIterable {
-
- case clearSky = "01d"
- case clearSkyNight = "01n"
- case fewClouds = "02d"
- case fewCloudsNight = "02n"
- case scatteredClouds = "03d"
- case scatteredCloudsNight = "03n"
- case brokenClouds = "04d"
- case brokenCloudsNight = "04n"
- case showerRain = "09d"
- case showerRainNight = "09n"
- case rain = "10d"
- case rainNight = "10n"
- case thunderstorm = "11d"
- case thunderstormNight = "11n"
- case snow = "13d"
- case snowNight = "13n"
- case mist = "50d"
- case mistNight = "50n"
-
-}
-
-@available(iOS 13.0, macOS 11.0, tvOS 13.0, watchOS 6.0, *)
-public extension WeatherIcon {
-
- var systemImageName: String {
- makeIconName(filled: false)
- }
-
- var systemImageNameFilled: String {
- makeIconName(filled: true)
- }
-
- #if canImport(UIKit)
-
- func filledUIImage(withConfiguration configuration: UIImage.Configuration? = nil) -> UIImage? {
- UIImage(systemName: systemImageNameFilled, withConfiguration: configuration)
- }
-
- func outlineUIImage(withConfiguration configuration: UIImage.Configuration? = nil) -> UIImage? {
- UIImage(systemName: systemImageName, withConfiguration: configuration)
- }
-
- #elseif canImport(AppKit)
-
- func filledNSImage(accessibilityDescription: String? = nil) -> NSImage? {
- NSImage(systemSymbolName: systemImageNameFilled, accessibilityDescription: accessibilityDescription)
- }
-
- func outlineNSImage(accessibilityDescription: String? = nil) -> NSImage? {
- NSImage(systemSymbolName: systemImageName, accessibilityDescription: accessibilityDescription)
- }
-
- #endif
-
- private func makeIconName(filled: Bool) -> String {
- let iconName: String
- switch self {
- case .clearSky:
- iconName = "sun.max"
- case .clearSkyNight:
- iconName = "moon"
- case .fewClouds:
- iconName = "cloud.sun"
- case .fewCloudsNight:
- iconName = "cloud.moon"
- case .scatteredClouds, .scatteredCloudsNight:
- iconName = "cloud"
- case .brokenClouds, .brokenCloudsNight:
- iconName = "smoke"
- case .showerRain, .showerRainNight:
- iconName = "cloud.rain"
- case .rain:
- iconName = "cloud.sun.rain"
- case .rainNight:
- iconName = "cloud.moon.rain"
- case .thunderstorm, .thunderstormNight:
- iconName = "cloud.bolt.rain"
- case .snow, .snowNight:
- return "snow"
- case .mist, .mistNight:
- iconName = "cloud.fog"
- }
-
- return iconName + (filled ? ".fill" : "")
- }
-
-}
diff --git a/Sources/HPOpenWeather/DataTypes/Wind.swift b/Sources/HPOpenWeather/DataTypes/Wind.swift
deleted file mode 100644
index e52ba0b..0000000
--- a/Sources/HPOpenWeather/DataTypes/Wind.swift
+++ /dev/null
@@ -1,13 +0,0 @@
-import Foundation
-
-/// Type that holds information about wind speed and direction measured in degrees
-public struct Wind: Codable, Equatable, Hashable {
-
- /// The current wind speed depending on the request's unit (metric: meter/second, imperial: miles/hour)
- public let speed: Double?
- /// Wind gust speed (metric: meter/sec, imperial: miles/hour)
- public let gust: Double?
- /// The wind direction measured in degrees from North
- public let degrees: Double?
-
-}
diff --git a/Sources/HPOpenWeather/Extensions/URLQueryItemsBuilder+Extensions.swift b/Sources/HPOpenWeather/Extensions/URLQueryItemsBuilder+Extensions.swift
deleted file mode 100644
index e86e6cf..0000000
--- a/Sources/HPOpenWeather/Extensions/URLQueryItemsBuilder+Extensions.swift
+++ /dev/null
@@ -1,12 +0,0 @@
-import HPNetwork
-
-extension URLBuilder {
-
- static let weatherBase: URLBuilder = {
- URLBuilder(host: "api.openweathermap.org")
- .addingPathComponent("data")
- .addingPathComponent("2.5")
- .addingPathComponent("onecall")
- }()
-
-}
diff --git a/Sources/HPOpenWeather/DataTypes/City.swift b/Sources/HPOpenWeather/Models/City.swift
similarity index 89%
rename from Sources/HPOpenWeather/DataTypes/City.swift
rename to Sources/HPOpenWeather/Models/City.swift
index c41e982..09c2570 100644
--- a/Sources/HPOpenWeather/DataTypes/City.swift
+++ b/Sources/HPOpenWeather/Models/City.swift
@@ -2,7 +2,7 @@ import Foundation
import CoreLocation
/// Type that holds information about the reqeuest's nearest city
-public struct City: Codable, Equatable, Hashable {
+public struct City: Codable, Equatable, Hashable, Identifiable {
/// The ID assigned to the city
public let id: Int
diff --git a/Sources/HPOpenWeather/DataTypes/DailyTemperature.swift b/Sources/HPOpenWeather/Models/DailyTemperature.swift
similarity index 74%
rename from Sources/HPOpenWeather/DataTypes/DailyTemperature.swift
rename to Sources/HPOpenWeather/Models/DailyTemperature.swift
index d323bd6..fa9a51a 100644
--- a/Sources/HPOpenWeather/DataTypes/DailyTemperature.swift
+++ b/Sources/HPOpenWeather/Models/DailyTemperature.swift
@@ -3,17 +3,17 @@ import Foundation
/// Type that holds information about daily temperature changes
public struct DailyTemperature: Codable, Equatable, Hashable {
- /// Day temperature.
+ /// Day temperature.
public let day: Double
- /// Night temperature.
+ /// Night temperature.
public let night: Double
- /// Minimum daily temperature.
+ /// Minimum daily temperature.
public let min: Double?
- /// Max daily temperature.
+ /// Max daily temperature.
public let max: Double?
- /// Evening temperature.
+ /// Evening temperature.
public let evening: Double
- /// Morning temperature.
+ /// Morning temperature.
public let morning: Double
enum CodingKeys: String, CodingKey {
diff --git a/Sources/HPOpenWeather/DataTypes/Forecasts/BasicWeather.swift b/Sources/HPOpenWeather/Models/Forecasts/BasicWeather.swift
similarity index 100%
rename from Sources/HPOpenWeather/DataTypes/Forecasts/BasicWeather.swift
rename to Sources/HPOpenWeather/Models/Forecasts/BasicWeather.swift
diff --git a/Sources/HPOpenWeather/Models/Forecasts/CurrentWeather.swift b/Sources/HPOpenWeather/Models/Forecasts/CurrentWeather.swift
new file mode 100644
index 0000000..3638d71
--- /dev/null
+++ b/Sources/HPOpenWeather/Models/Forecasts/CurrentWeather.swift
@@ -0,0 +1,75 @@
+import Foundation
+
+public struct CurrentWeather: BasicWeatherResponse, SunResponse {
+
+ // MARK: - Coding Keys
+
+ enum CodingKeys: String, CodingKey {
+ case feelsLikeTemperature = "feels_like"
+ case snow
+ case rain
+ case timestamp = "dt"
+ case actualTemperature = "temp"
+ case pressure
+ case humidity
+ case dewPoint = "dew_point"
+ case uvIndex = "uvi"
+ case cloudCoverage = "clouds"
+ case visibility
+ case windSpeed = "wind_speed"
+ case windGust = "wind_gust"
+ case windDirection = "wind_deg"
+ case weatherArray = "weather"
+ case sunrise
+ case sunset
+ }
+
+ // MARK: - Properties
+
+ public let timestamp: Date
+ public let pressure: Double?
+ public let humidity: Double?
+ public let dewPoint: Double?
+ public let uvIndex: Double?
+ public let visibility: Double?
+ public let cloudCoverage: Double?
+ public let rain: Precipitation?
+ public let snow: Precipitation?
+
+ // Temperature
+
+ private let actualTemperature: Double
+ private let feelsLikeTemperature: Double
+
+ public var temperature: Temperature {
+ Temperature(actual: actualTemperature, feelsLike: feelsLikeTemperature)
+ }
+
+ // Weather Conditions
+
+ private let weatherArray: [WeatherCondition]
+
+ public var condition: WeatherCondition? {
+ weatherArray.first
+ }
+
+ // Wind
+
+ private let windSpeed: Double?
+ private let windGust: Double?
+ private let windDirection: Double?
+
+ public var wind: Wind {
+ Wind(speed: windSpeed, gust: windGust, degrees: windDirection)
+ }
+
+ // Sun
+
+ private let sunrise: Date
+ private let sunset: Date
+
+ public var sun: Sun {
+ Sun(sunset: sunset, sunrise: sunrise)
+ }
+
+}
diff --git a/Sources/HPOpenWeather/Models/Forecasts/DailyForecast.swift b/Sources/HPOpenWeather/Models/Forecasts/DailyForecast.swift
new file mode 100644
index 0000000..1b9f063
--- /dev/null
+++ b/Sources/HPOpenWeather/Models/Forecasts/DailyForecast.swift
@@ -0,0 +1,70 @@
+import Foundation
+
+public struct DailyForecast: BasicWeatherResponse, SunResponse {
+
+ // MARK: - Coding Keys
+
+ enum CodingKeys: String, CodingKey {
+ case feelsLikeTemperature = "feels_like"
+ case totalRain = "rain"
+ case totalSnow = "snow"
+ case timestamp = "dt"
+ case temperature = "temp"
+ case pressure
+ case humidity
+ case dewPoint = "dew_point"
+ case uvIndex = "uvi"
+ case cloudCoverage = "clouds"
+ case visibility
+ case windSpeed = "wind_speed"
+ case windGust = "wind_gust"
+ case windDirection = "wind_deg"
+ case weatherArray = "weather"
+ case sunrise
+ case sunset
+ }
+
+ // MARK: - Properties
+
+ public let temperature: DailyTemperature
+ public let feelsLikeTemperature: DailyTemperature
+ public let totalRain: Double?
+ public let totalSnow: Double?
+
+ public let timestamp: Date
+ public let pressure: Double?
+ public let humidity: Double?
+ public let dewPoint: Double?
+ public let uvIndex: Double?
+ public let visibility: Double?
+ public let cloudCoverage: Double?
+
+ // Weather Conditions
+
+ private let weatherArray: [WeatherCondition]
+
+ public var condition: WeatherCondition? {
+ weatherArray.first
+ }
+
+ // Wind
+
+ private let windSpeed: Double?
+ private let windGust: Double?
+ private let windDirection: Double?
+
+ public var wind: Wind {
+ Wind(speed: windSpeed, gust: windGust, degrees: windDirection)
+ }
+
+ // Sun
+
+ private let sunrise: Date
+ private let sunset: Date
+
+ public var sun: Sun {
+ Sun(sunset: sunset, sunrise: sunrise)
+ }
+
+}
+
diff --git a/Sources/HPOpenWeather/Models/Forecasts/HourlyForecast.swift b/Sources/HPOpenWeather/Models/Forecasts/HourlyForecast.swift
new file mode 100644
index 0000000..8a2ffbb
--- /dev/null
+++ b/Sources/HPOpenWeather/Models/Forecasts/HourlyForecast.swift
@@ -0,0 +1,64 @@
+import Foundation
+
+public struct HourlyForecast: BasicWeatherResponse {
+
+ // MARK: - Coding Keys
+
+ enum CodingKeys: String, CodingKey {
+ case actualTemperature = "temp"
+ case feelsLikeTemperature = "feels_like"
+ case snow
+ case rain
+ case timestamp = "dt"
+ case pressure
+ case humidity
+ case dewPoint = "dew_point"
+ case uvIndex = "uvi"
+ case cloudCoverage = "clouds"
+ case visibility
+ case windSpeed = "wind_speed"
+ case windGust = "wind_gust"
+ case windDirection = "wind_deg"
+ case weatherArray = "weather"
+ }
+
+ // MARK: - Properties
+
+ public let timestamp: Date
+ public let pressure: Double?
+ public let humidity: Double?
+ public let dewPoint: Double?
+ public let uvIndex: Double?
+ public let visibility: Double?
+ public let cloudCoverage: Double?
+ public let rain: Precipitation?
+ public let snow: Precipitation?
+
+ // Temperature
+
+ private let actualTemperature: Double
+ private let feelsLikeTemperature: Double
+
+ public var temperature: Temperature {
+ Temperature(actual: actualTemperature, feelsLike: feelsLikeTemperature)
+ }
+
+ // Wind
+
+ private let windSpeed: Double?
+ private let windGust: Double?
+ private let windDirection: Double?
+
+ public var wind: Wind {
+ Wind(speed: windSpeed, gust: windGust, degrees: windDirection)
+ }
+
+ // Weather
+
+ private let weatherArray: [WeatherCondition]
+
+ public var weather: [WeatherCondition] {
+ weatherArray
+ }
+
+}
diff --git a/Sources/HPOpenWeather/Models/Precipitation.swift b/Sources/HPOpenWeather/Models/Precipitation.swift
new file mode 100644
index 0000000..fcdccc7
--- /dev/null
+++ b/Sources/HPOpenWeather/Models/Precipitation.swift
@@ -0,0 +1,32 @@
+import Foundation
+
+/// Type that holds information about recent precipitation
+public struct Precipitation: Codable, Equatable, Hashable {
+
+ enum CodingKeys: String, CodingKey {
+ case lastHour = "1h"
+ case lastThreeHours = "3h"
+ }
+
+ /// Precipitation volume for the last 1 hour, measured in mm
+ public var lastHour: Double?
+ /// Precipitation volume for the last 3 hours, measured in mm
+ public var lastThreeHours: Double?
+
+ /// A convertible measurement of how much precipitation occured in the last hour if any
+ public var lastHourMeasurement: Measurement? {
+ guard let lastHour = lastHour else {
+ return nil
+ }
+ return Measurement(value: lastHour, unit: .millimeters)
+ }
+
+ /// A convertible measurement of how much precipitation occured in the last three hours if any
+ public var lastThreeHoursMeasurement: Measurement? {
+ guard let lastThreeHours = lastThreeHours else {
+ return nil
+ }
+ return Measurement(value: lastThreeHours, unit: .millimeters)
+ }
+
+}
diff --git a/Sources/HPOpenWeather/DataTypes/Sun.swift b/Sources/HPOpenWeather/Models/Sun.swift
similarity index 69%
rename from Sources/HPOpenWeather/DataTypes/Sun.swift
rename to Sources/HPOpenWeather/Models/Sun.swift
index 880baa1..778dbfa 100644
--- a/Sources/HPOpenWeather/DataTypes/Sun.swift
+++ b/Sources/HPOpenWeather/Models/Sun.swift
@@ -2,10 +2,10 @@ import Foundation
/// Type that holds information about sunrise and sunset times in UTC time
public struct Sun: Codable, Equatable, Hashable {
-
+
/// Sunset time
public let sunset: Date
- /// Sunrise timeWind speed. Unit Default: meter/sec, Metric: meter/sec, Imperial: miles/hour.
+ /// Sunrise time
public let sunrise: Date
-
+
}
diff --git a/Sources/HPOpenWeather/Models/Temperature.swift b/Sources/HPOpenWeather/Models/Temperature.swift
new file mode 100644
index 0000000..f2bc8fd
--- /dev/null
+++ b/Sources/HPOpenWeather/Models/Temperature.swift
@@ -0,0 +1,33 @@
+import Foundation
+
+/// Type that holds information about daily temperature changes
+public struct Temperature: Codable, Equatable, Hashable {
+
+ /// The actually measured temperature
+ public let actual: Double
+ /// The feels-like temperature
+ public let feelsLike: Double
+
+ /// A convertible measurement of the actually measured temperature
+ public var actualMeasurement: Measurement {
+ actualMeasurement(units: OpenWeather.shared.units)
+ }
+
+ /// A convertible measurement of the actually measured temperature
+ /// - Parameter units: The units to use when formatting the `actual` property
+ public func actualMeasurement(units: WeatherResponse.Units) -> Measurement {
+ Measurement(value: actual, unit: units.temperatureUnit)
+ }
+
+ /// A convertible measurement of how the actually measured temperature feels like
+ public var feelsLikeMeasurement: Measurement {
+ feelsLikeMeasurement(units: OpenWeather.shared.units)
+ }
+
+ /// A convertible measurement of how the actually measured temperature feels like
+ /// - Parameter units: The units to use when formatting the `feelsLike` property
+ public func feelsLikeMeasurement(units: WeatherResponse.Units) -> Measurement {
+ Measurement(value: feelsLike, unit: units.temperatureUnit)
+ }
+
+}
diff --git a/Sources/HPOpenWeather/Models/WeatherAlert.swift b/Sources/HPOpenWeather/Models/WeatherAlert.swift
new file mode 100644
index 0000000..7659d38
--- /dev/null
+++ b/Sources/HPOpenWeather/Models/WeatherAlert.swift
@@ -0,0 +1,25 @@
+import Foundation
+
+/// Type that holds information about weather alerts
+public struct WeatherAlert: Codable, Hashable, Equatable {
+
+ /// Name of the alert source. Please read here the full list of alert sources
+ public let senderName: String
+ /// Alert event name
+ public let eventName: String
+ //// Date and time of the start of the alert
+ public let startDate: Date
+ //// Date and time of the end of the alert
+ public let endDate: Date
+ /// Description of the alert
+ public let description: String
+
+ enum CodingKeys: String, CodingKey {
+ case senderName = "sender_name"
+ case eventName = "event"
+ case startDate = "start"
+ case endDate = "end"
+ case description
+ }
+
+}
diff --git a/Sources/HPOpenWeather/DataTypes/WeatherCondition.swift b/Sources/HPOpenWeather/Models/WeatherCondition.swift
similarity index 92%
rename from Sources/HPOpenWeather/DataTypes/WeatherCondition.swift
rename to Sources/HPOpenWeather/Models/WeatherCondition.swift
index 8478364..7f95d66 100644
--- a/Sources/HPOpenWeather/DataTypes/WeatherCondition.swift
+++ b/Sources/HPOpenWeather/Models/WeatherCondition.swift
@@ -10,6 +10,6 @@ public struct WeatherCondition: Codable, Equatable, Hashable {
/// The weather condition within the group
public let description: String
/// The ID of the corresponding weather icon
- public let icon: WeatherIcon
+ public let icon: WeatherIcon
}
diff --git a/Sources/HPOpenWeather/Models/WeatherIcon.swift b/Sources/HPOpenWeather/Models/WeatherIcon.swift
new file mode 100644
index 0000000..bbb1a14
--- /dev/null
+++ b/Sources/HPOpenWeather/Models/WeatherIcon.swift
@@ -0,0 +1,95 @@
+#if canImport(UIKit)
+import UIKit
+#elseif canImport(AppKit)
+import AppKit
+#endif
+import Foundation
+
+public enum WeatherIcon: String, Codable, CaseIterable {
+
+ case clearSky = "01d"
+ case clearSkyNight = "01n"
+ case fewClouds = "02d"
+ case fewCloudsNight = "02n"
+ case scatteredClouds = "03d"
+ case scatteredCloudsNight = "03n"
+ case brokenClouds = "04d"
+ case brokenCloudsNight = "04n"
+ case showerRain = "09d"
+ case showerRainNight = "09n"
+ case rain = "10d"
+ case rainNight = "10n"
+ case thunderstorm = "11d"
+ case thunderstormNight = "11n"
+ case snow = "13d"
+ case snowNight = "13n"
+ case mist = "50d"
+ case mistNight = "50n"
+
+}
+
+@available(iOS 13.0, macOS 11.0, tvOS 13.0, watchOS 6.0, *)
+public extension WeatherIcon {
+
+ var systemImageName: String {
+ makeIconName(filled: false)
+ }
+
+ var systemImageNameFilled: String {
+ makeIconName(filled: true)
+ }
+
+#if canImport(UIKit)
+
+ func filledUIImage(withConfiguration configuration: UIImage.Configuration? = nil) -> UIImage? {
+ UIImage(systemName: systemImageNameFilled, withConfiguration: configuration)
+ }
+
+ func outlineUIImage(withConfiguration configuration: UIImage.Configuration? = nil) -> UIImage? {
+ UIImage(systemName: systemImageName, withConfiguration: configuration)
+ }
+
+#elseif canImport(AppKit)
+
+ func filledNSImage(accessibilityDescription: String? = nil) -> NSImage? {
+ NSImage(systemSymbolName: systemImageNameFilled, accessibilityDescription: accessibilityDescription)
+ }
+
+ func outlineNSImage(accessibilityDescription: String? = nil) -> NSImage? {
+ NSImage(systemSymbolName: systemImageName, accessibilityDescription: accessibilityDescription)
+ }
+
+#endif
+
+ private func makeIconName(filled: Bool) -> String {
+ let iconName: String
+ switch self {
+ case .clearSky:
+ iconName = "sun.max"
+ case .clearSkyNight:
+ iconName = "moon"
+ case .fewClouds:
+ iconName = "cloud.sun"
+ case .fewCloudsNight:
+ iconName = "cloud.moon"
+ case .scatteredClouds, .scatteredCloudsNight:
+ iconName = "cloud"
+ case .brokenClouds, .brokenCloudsNight:
+ iconName = "smoke"
+ case .showerRain, .showerRainNight:
+ iconName = "cloud.rain"
+ case .rain:
+ iconName = "cloud.sun.rain"
+ case .rainNight:
+ iconName = "cloud.moon.rain"
+ case .thunderstorm, .thunderstormNight:
+ iconName = "cloud.bolt.rain"
+ case .snow, .snowNight:
+ return "snow"
+ case .mist, .mistNight:
+ iconName = "cloud.fog"
+ }
+ return iconName + (filled ? ".fill" : "")
+ }
+
+}
diff --git a/Sources/HPOpenWeather/Models/Wind.swift b/Sources/HPOpenWeather/Models/Wind.swift
new file mode 100644
index 0000000..414e32d
--- /dev/null
+++ b/Sources/HPOpenWeather/Models/Wind.swift
@@ -0,0 +1,27 @@
+import Foundation
+
+/// Type that holds information about wind speed and direction measured in degrees
+public struct Wind: Codable, Equatable, Hashable {
+
+ /// The current wind speed depending on the request's unit (metric: meter/second, imperial: miles/hour)
+ public let speed: Double?
+ /// Wind gust speed (metric: meter/sec, imperial: miles/hour)
+ public let gust: Double?
+ /// The wind direction measured in degrees from North
+ public let degrees: Double?
+
+ /// A measurement of the `speed` property if existing, measured in the units currently specified in `OpenWeather.shared`
+ public var speedMeasurement: Measurement? {
+ speedMeasurement(units: OpenWeather.shared.units)
+ }
+
+ /// A measurement of the `speed` property if existing, measured in the passed in units
+ /// - Parameter units: The units to use when formatting the `speed` property
+ public func speedMeasurement(units: WeatherResponse.Units) -> Measurement? {
+ guard let speed = speed else {
+ return nil
+ }
+ return Measurement(value: speed, unit: units.windSpeedUnit)
+ }
+
+}
diff --git a/Sources/HPOpenWeather/OpenWeather.swift b/Sources/HPOpenWeather/OpenWeather.swift
index 4d86e54..3ab6e95 100644
--- a/Sources/HPOpenWeather/OpenWeather.swift
+++ b/Sources/HPOpenWeather/OpenWeather.swift
@@ -1,18 +1,26 @@
import CoreLocation
import Foundation
-import HPNetwork
+/// A type to request current weather conditions and forecasts
public final class OpenWeather {
// MARK: - Nested Types
/// Type that can be used to configure all settings at once
public struct Settings {
+ /// The API key to use for weather requests
let apiKey : String
- let language: RequestLanguage
- let units: RequestUnits
-
- public init(apiKey: String, language: RequestLanguage = .english, units: RequestUnits = .metric) {
+ /// The language that will be used in weather responses
+ let language: WeatherResponse.Language
+ /// The units that will be used in weather responses
+ let units: WeatherResponse.Units
+
+ /// Initialises a new settings instance
+ /// - Parameters:
+ /// - apiKey: The API key to use for weather requests
+ /// - language: The language that will be used in weather responses
+ /// - units: The units that will be used in weather responses
+ public init(apiKey: String, language: WeatherResponse.Language = .english, units: WeatherResponse.Units = .metric) {
self.language = language
self.units = units
self.apiKey = apiKey
@@ -21,22 +29,26 @@ public final class OpenWeather {
// MARK: - Properties
- /// A shared instance of the weather client
+ /// A shared instance of the weather client
public static let shared = OpenWeather()
/// The OpenWeatherMap API key to authorize requests
public var apiKey : String?
/// The language that should be used in API responses
- public var language: RequestLanguage = .english
+ public var language: WeatherResponse.Language = .english
/// The units that should be used to format the API responses
- public var units: RequestUnits = .metric
+ public var units: WeatherResponse.Units = .metric
// MARK: - Init
+ /// Initialised a new instance of `OpenWeather` and applies the specified API key
+ /// - Parameter apiKey: the API key to authenticate with the OpenWeatherMap API
public init(apiKey: String? = nil) {
self.apiKey = apiKey
}
+ /// Initialised a new instance of `OpenWeather` and applies the specified settimgs
+ /// - Parameter settings: the settings to apply, including API key, language and units
public init(settings: Settings) {
self.apiKey = settings.apiKey
self.language = settings.language
@@ -45,62 +57,72 @@ public final class OpenWeather {
// MARK: - Sending Requests
- public func requestWeather(
- coordinate: CLLocationCoordinate2D,
- excludedFields: [ExcludableField]? = nil,
- date: Date? = nil,
- urlSession: URLSession = .shared,
- finishingQueue: DispatchQueue = .main,
- progressHandler: ProgressHandler? = nil,
- completion: @escaping (Result) -> Void)
- {
- let request = WeatherRequest(
- coordinate: coordinate,
- excludedFields: excludedFields,
- date: date,
- urlSession: urlSession,
- finishingQueue: finishingQueue
- )
- schedule(request, progressHandler: progressHandler, completion: completion)
- }
-
- /// Sends the specified request to the OpenWeather API
- /// - Parameters:
- /// - request: The request object that holds information about request location, date, etc.
- /// - completion: The completion block that will be called once the networking finishes
- /// - Returns: A network task that can be used to cancel the request
- public func schedule(
- _ request: WeatherRequest,
- progressHandler: ProgressHandler? = nil,
- completion: @escaping (Result) -> Void)
- {
+ /// Sends the specified request to the OpenWeather API
+ /// - Parameters:
+ /// - coordinate: The coordinate for which the weather will be requested
+ /// - excludedFields: An array specifying the fields that will be excluded from the response
+ /// - date: The date for which you want to request the weather. If no date is provided, the current weather will be retrieved
+ /// - urlSession: The `URLSession` that will be used schedule requests
+ /// - Returns: A weather response object
+ public func weatherResponse(
+ coordinate: CLLocationCoordinate2D,
+ excludedFields: [WeatherRequest.ExcludableField]? = nil,
+ date: Date? = nil,
+ urlSession: URLSession = .shared
+ ) async throws -> WeatherResponse {
+ let request = WeatherRequest(
+ coordinate: coordinate,
+ excludedFields: excludedFields,
+ date: date
+ )
+ return try await weatherResponse(request, urlSession: urlSession)
+ }
+
+ /// Sends the specified request to the OpenWeather API
+ /// - Parameters:
+ /// - request: The request object that holds information about request location, date, etc.
+ /// - urlSession: The `URLSession` that will be used schedule requests
+ /// - Returns: A weather response object
+ public func weatherResponse(_ request: WeatherRequest, urlSession: URLSession = .shared) async throws -> WeatherRequest.Output {
guard let apiKey = apiKey else {
- request.finishingQueue.async {
- completion(.failure(NSError.noApiKey))
- }
- return
+ throw NSError.noApiKey
}
let settings = Settings(apiKey: apiKey, language: language, units: units)
- do {
- let networkRequest = try request.makeNetworkRequest(settings: settings)
- Network.shared.schedule(request: networkRequest, progressHandler: progressHandler, completion: completion)
- } catch let error {
- request.finishingQueue.async {
+ let networkRequest = try request.makeNetworkRequest(settings: settings, urlSession: urlSession)
+ var response = try await networkRequest.response().output
+ response.units = settings.units
+ response.language = settings.language
+ return response
+ }
+
+ /// Sends the specified request to the OpenWeather API
+ /// - Parameters:
+ /// - request: The request object that holds information about request location, date, etc.
+ /// - urlSession: The `URLSession` that will be used schedule requests
+ /// - completion: A completion that will be called with the result of the network request
+ /// - Returns: A network task that can be used to cancel the request
+ @discardableResult
+ public func schedule(_ request: WeatherRequest, urlSession: URLSession = .shared, completion: @escaping (Result) -> Void) -> Task {
+ Task {
+ do {
+ let response = try await weatherResponse(request, urlSession: urlSession)
+ completion(.success(response))
+ } catch {
completion(.failure(error))
}
}
}
- // MARK: - Applying Settings
+ // MARK: - Applying Settings
- /// Applies new settings to the weather client
- /// - Parameter settings: The weather client settings, including an API key, language and units
- public func apply(_ settings: Settings) {
- apiKey = settings.apiKey
- language = settings.language
- units = settings.units
- }
+ /// Applies new settings to the weather client
+ /// - Parameter settings: The weather client settings, including an API key, language and units
+ public func apply(_ settings: Settings) {
+ apiKey = settings.apiKey
+ language = settings.language
+ units = settings.units
+ }
}
diff --git a/Sources/HPOpenWeather/Requests/APINetworkRequest.swift b/Sources/HPOpenWeather/Requests/APINetworkRequest.swift
index 5b67b9f..9e799ec 100644
--- a/Sources/HPOpenWeather/Requests/APINetworkRequest.swift
+++ b/Sources/HPOpenWeather/Requests/APINetworkRequest.swift
@@ -1,25 +1,30 @@
import Foundation
import HPNetwork
-public struct APINetworkRequest: DecodableRequest {
+struct APINetworkRequest: DecodableRequest {
- public let url: URL?
- public let urlSession: URLSession
- public let finishingQueue: DispatchQueue
- public let requestMethod: NetworkRequestMethod = .get
- public let headerFields = [NetworkRequestHeaderField.contentTypeJSON]
+ typealias Output = WeatherResponse
- public let decoder: JSONDecoder = {
- let decoder = JSONDecoder()
- decoder.dateDecodingStrategy = .secondsSince1970
- return decoder
- }()
+ static let decoder: JSONDecoder = {
+ let decoder = JSONDecoder()
+ decoder.dateDecodingStrategy = .secondsSince1970
+ return decoder
+ }()
- public func makeURL() throws -> URL {
- guard let url = url else {
- throw NSError(code: 6, description: "Could not create URL")
- }
- return url
- }
+ let url: URL?
+ let urlSession: URLSession
+ let requestMethod: NetworkRequestMethod = .get
+ let headerFields = [NetworkRequestHeaderField.contentTypeJSON]
+
+ var decoder: JSONDecoder {
+ APINetworkRequest.decoder
+ }
+
+ func makeURL() throws -> URL {
+ guard let url = url else {
+ throw NSError(code: 6, description: "Could not create URL")
+ }
+ return url
+ }
}
diff --git a/Sources/HPOpenWeather/Requests/ExcludableField.swift b/Sources/HPOpenWeather/Requests/ExcludableField.swift
deleted file mode 100644
index c2e5c43..0000000
--- a/Sources/HPOpenWeather/Requests/ExcludableField.swift
+++ /dev/null
@@ -1,11 +0,0 @@
-import Foundation
-
-public enum ExcludableField: String {
-
- case current
- case minutely
- case hourly
- case daily
- case alerts
-
-}
diff --git a/Sources/HPOpenWeather/Requests/RequestLanguage.swift b/Sources/HPOpenWeather/Requests/RequestLanguage.swift
deleted file mode 100644
index 4c25782..0000000
--- a/Sources/HPOpenWeather/Requests/RequestLanguage.swift
+++ /dev/null
@@ -1,52 +0,0 @@
-import Foundation
-
-/// The language that should be used in API responses for example for weather condition descriptions
-public enum RequestLanguage: String {
-
- case afrikaans = "af"
- case arabic = "ar"
- case azerbaijani = "az"
- case bulgarian = "bg"
- case catalan = "ca"
- case czech = "cz"
- case danish = "da"
- case german = "de"
- case greek = "el"
- case english = "en"
- case basque = "eu"
- case persian = "fa"
- case finnish = "fi"
- case french = "fr"
- case galician = "gl"
- case hebrew = "he"
- case hindi = "hi"
- case croatian = "hr"
- case hungarian = "hu"
- case indonesian = "id"
- case italian = "it"
- case japanese = "ja"
- case korean = "kr"
- case latvian = "la"
- case lithuanian = "lt"
- case macedonian = "mk"
- case norwegian = "no"
- case dutch = "nl"
- case polish = "pl"
- case portuguese = "pt"
- case portugueseBrasil = "pt_br"
- case romanian = "ro"
- case russian = "ru"
- case swedish = "sv"
- case slovak = "sk"
- case slovenian = "sl"
- case spanish = "es"
- case serbian = "sr"
- case thai = "th"
- case turkish = "tr"
- case ukrainian = "ua"
- case vietnamese = "vi"
- case chineseSimplified = "zh_cn"
- case chineseTraditional = "zh_tw"
- case zulu = "zu"
-
-}
diff --git a/Sources/HPOpenWeather/Requests/RequestUnits.swift b/Sources/HPOpenWeather/Requests/RequestUnits.swift
deleted file mode 100644
index 3308807..0000000
--- a/Sources/HPOpenWeather/Requests/RequestUnits.swift
+++ /dev/null
@@ -1,13 +0,0 @@
-import Foundation
-
-/// The units that should the data in the API responses should be formatted in
-public enum RequestUnits: String {
-
- /// Temperature in Kelvin and wind speed in meter/sec
- case standard
- /// Temperature in Celsius and wind speed in meter/sec
- case metric
- /// Temperature in Fahrenheit and wind speed in miles/hour
- case imperial
-
-}
diff --git a/Sources/HPOpenWeather/Requests/WeatherRequest+Combine.swift b/Sources/HPOpenWeather/Requests/WeatherRequest+Combine.swift
index a539865..d32b1f5 100644
--- a/Sources/HPOpenWeather/Requests/WeatherRequest+Combine.swift
+++ b/Sources/HPOpenWeather/Requests/WeatherRequest+Combine.swift
@@ -1,19 +1,25 @@
-#if canImport(Combine)
import Combine
import Foundation
-@available(macOS 10.15, iOS 13.0, tvOS 13.0, watchOS 6.0, *)
public extension WeatherRequest {
- func publisher(apiKey: String, language: RequestLanguage = .english, units: RequestUnits = .metric) -> AnyPublisher