From 5449a64ccc29f56618412d746f785a395d6d15a7 Mon Sep 17 00:00:00 2001 From: "RobLabs.com" Date: Mon, 11 Apr 2022 15:13:15 -0700 Subject: [PATCH 1/2] Allow API customers to set the UnitTemperature to get either US or SI (metric) results from the API --- .../services/calls/NWS+Forecast.swift | 8 +++- .../GetForecastIntegrationTests.swift | 38 +++++++++++++++++++ 2 files changed, 45 insertions(+), 1 deletion(-) diff --git a/Sources/NationalWeatherService/services/calls/NWS+Forecast.swift b/Sources/NationalWeatherService/services/calls/NWS+Forecast.swift index 72a878b..bd517df 100644 --- a/Sources/NationalWeatherService/services/calls/NWS+Forecast.swift +++ b/Sources/NationalWeatherService/services/calls/NWS+Forecast.swift @@ -10,10 +10,16 @@ import Foundation extension NationalWeatherService { public typealias ForecastHandler = (Result) -> Void + /// Allow API customers to set the [UnitTemperature](https://developer.apple.com/documentation/foundation/unittemperature) + /// to get ["*US customary or SI (metric) units in textual output*"](https://www.weather.gov/documentation/services-web-api#/default/gridpoint_forecast) + public static var units: UnitTemperature = .celsius + fileprivate func loadForecast(at url: URL, then handler: @escaping ForecastHandler) { var components = URLComponents(url: url, resolvingAgainstBaseURL: false)! + + let units: String = NationalWeatherService.units == .celsius ? "si" : "us" components.queryItems = [ - URLQueryItem(name: "units", value: "si") + URLQueryItem(name: "units", value: units) ] self.load(at: components.url!, as: Forecast.self, then: handler) diff --git a/Tests/NationalWeatherServiceTests/integration/GetForecastIntegrationTests.swift b/Tests/NationalWeatherServiceTests/integration/GetForecastIntegrationTests.swift index b82cc6b..a85910d 100644 --- a/Tests/NationalWeatherServiceTests/integration/GetForecastIntegrationTests.swift +++ b/Tests/NationalWeatherServiceTests/integration/GetForecastIntegrationTests.swift @@ -2,6 +2,7 @@ import XCTest @testable import NationalWeatherService final class GetForecastIntegrationTests: XCTestCase { + /// Get forecast without setting `NationalWeatherService.units` func testGetForecastForLocation() throws { let forecastExpectation = self.expectation(description: "get forecast expectation") nws.forecast(latitude: 47.6174, longitude: -122.2017) { result in @@ -15,7 +16,44 @@ final class GetForecastIntegrationTests: XCTestCase { wait(for: [forecastExpectation], timeout: 5) } + + /// Get forecast by setting `NationalWeatherService.units` to `.fahrenheit` + func testGetForecastFahrenheit() throws { + let forecastExpectation = self.expectation(description: "get forecast expectation") + + NationalWeatherService.units = .fahrenheit + nws.forecast(latitude: 47.6174, longitude: -122.2017) { result in + XCTAssertSuccess(result) + + let forecast = try! result.get() + print(forecast) + XCTAssertFalse(forecast.periods.isEmpty) + forecastExpectation.fulfill() + } + + wait(for: [forecastExpectation], timeout: 5) + } + + /// Get forecast by setting `NationalWeatherService.units` to `.celsius` + func testGetForecastCelsius() throws { + let forecastExpectation = self.expectation(description: "get forecast expectation") + + NationalWeatherService.units = .celsius + nws.forecast(latitude: 47.6174, longitude: -122.2017) { result in + XCTAssertSuccess(result) + + let forecast = try! result.get() + + print(forecast) + XCTAssertFalse(forecast.periods.isEmpty) + + forecastExpectation.fulfill() + } + + wait(for: [forecastExpectation], timeout: 5) + } + func testGetHourlyForecast() throws { let hourlyForecastExpectation = self.expectation(description: "get hourly forecast expectation") nws.hourlyForecast(latitude: 47.6174, longitude: -122.2017) { result in From af78429f496023392893fde4ba27c7b68e3b6410 Mon Sep 17 00:00:00 2001 From: "RobLabs.com" Date: Tue, 24 Jan 2023 16:05:07 -0800 Subject: [PATCH 2/2] Swift Playground with Map & NWS Forecast --- .../Contents.swift | 56 +++++++++++++++++++ .../contents.xcplayground | 4 ++ .../timeline.xctimeline | 6 ++ 3 files changed, 66 insertions(+) create mode 100644 NationalWeatherService.playground/Contents.swift create mode 100644 NationalWeatherService.playground/contents.xcplayground create mode 100644 NationalWeatherService.playground/timeline.xctimeline diff --git a/NationalWeatherService.playground/Contents.swift b/NationalWeatherService.playground/Contents.swift new file mode 100644 index 0000000..78cebe6 --- /dev/null +++ b/NationalWeatherService.playground/Contents.swift @@ -0,0 +1,56 @@ +//: A MapKit based Playground + +import MapKit +import NationalWeatherService +import CoreLocation +import PlaygroundSupport + + +let nws = NationalWeatherService(userAgent: "(github.com/WeatherProvider, NationalWeatherService-Swift)") +let location = CLLocationCoordinate2DMake(47.6174, -122.2017) // Bellvue, Washington + +// Create a map annotation +let annotation = MKPointAnnotation() + +annotation.coordinate = location +annotation.title = "title" +annotation.subtitle = "subtitle" + +// Gets the forecast, organized into time periods (such as Afternoon, Evening, etc). +NationalWeatherService.units = .fahrenheit +nws.forecast(for: location) { result in + switch result { + case .success(let forecast): + print(forecast) + + let period = forecast.periods.first! + print(period) + + print(period.shortForecast) + annotation.title = period.shortForecast + + print(period.detailedForecast) + annotation.subtitle = period.detailedForecast + + case .failure(let error): + print(error) + } +} + +// Now let's create a MKMapView +let mapView = MKMapView(frame: CGRect(x:0, y:0, width:640, height:480)) + +// Define a region for our map view +var mapRegion = MKCoordinateRegion() + +let mapRegionSpan = 0.2 +mapRegion.center = location +mapRegion.span.latitudeDelta = mapRegionSpan +mapRegion.span.longitudeDelta = mapRegionSpan + +mapView.setRegion(mapRegion, animated: true) + +mapView.addAnnotation(annotation) + +// Add the created mapView to our Playground Live View +PlaygroundPage.current.liveView = mapView diff --git a/NationalWeatherService.playground/contents.xcplayground b/NationalWeatherService.playground/contents.xcplayground new file mode 100644 index 0000000..7627317 --- /dev/null +++ b/NationalWeatherService.playground/contents.xcplayground @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/NationalWeatherService.playground/timeline.xctimeline b/NationalWeatherService.playground/timeline.xctimeline new file mode 100644 index 0000000..bf468af --- /dev/null +++ b/NationalWeatherService.playground/timeline.xctimeline @@ -0,0 +1,6 @@ + + + + +