Environment:
Xcode Version 11.3 (11C29)
Apple Swift version 5.1.3
Scenario: Combine Neophyte attempting to learn URLSession.shared.dataTaskPublisher
Details:
I made a simple app to access weather data (any data) via two means:
1) Standard and
2) via Publisher
1) Here's the result: Weather data via Standard paradigm:
Sample(coord: DataTaskPublisher.Coord(lon: -0.13, lat: 51.51), weather: [DataTaskPublisher.Weather(id: 300, main: "Drizzle", description: "light intensity drizzle")], base: "stations", main: DataTaskPublisher.Main(temp: 280.32, pressure: 1012, humidity: 81, tempMin: 279.15, tempMax: 281.15), visibility: 10000, wind: DataTaskPublisher.Wind(speed: 4.1, deg: 80), clouds: DataTaskPublisher.Clouds(all: 90), dt: 1485789600.0, id: 2643743, name: "London")
2) However the following error result is what I get via Combine's Publisher paradigm:
2019-12-27 12:48:31.019760-0800 DataTaskPublisher[36228:13390491] Task <8770DDAB-78BC-48D1-BA6C-F5941742E4FA>.<2> finished with error [-999] Error Domain=NSURLErrorDomain Code=-999 "cancelled" UserInfo={NSErrorFailingURLStringKey=https://samples.openweathermap.org/data/2.5/weather?q=London,uk&appid=b6907d289e10d714a6e88b30761fae22, NSLocalizedDescription=cancelled, NSErrorFailingURLKey=https://samples.openweathermap.org/data/2.5/weather?q=London,uk&appid=b6907d289e10d714a6e88b30761fae22}
Here are the two codes (Standard, following with Publish):
import UIKit
let weatherURL = "https://samples.openweathermap.org/data/2.5/weather?q=London,uk&appid=b6907d289e10d714a6e88b30761fae22"
let calculationID = "51f82d8e-64ed-4d80-808c-b1c29c780d28"
let calculatorBase = "https://calculator-frontend-challenge.herokuapp.com/Calculations"
enum EndPoint {
case weather
case calc
func path() -> URL? {
switch self {
case .weather:
return URL(string: weatherURL)
default:
return nil
}
}
}
func doStandard() {
let url = EndPoint.weather.path()
let task = URLSession.shared.dataTask(with: url!) { (data: Data?, _: URLResponse?, error: Error?) -> Void in
do {
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
let result = try decoder.decode(Sample.self, from: data!)
print(result)
} catch let error as NSError {
print(error)
}
}
task.resume()
}
// ---------------------------------------------------------------------------
func doPublish() {
let url = EndPoint.weather.path()
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
let remoteDataPublisher = URLSession.shared.dataTaskPublisher(for: url!)
// the dataTaskPublisher output combination is (data: Data, response: URLResponse)
.map { $0.data }
.decode(type: Sample.self, decoder: decoder)
let _ = remoteDataPublisher
.sink(receiveCompletion: { completion in
print(".sink() received the completion", String(describing: completion))
switch completion {
case .finished:
break
case .failure(let anError):
print("received error: ", anError)
}
}, receiveValue: { someValue in
print(".sink() received \(someValue)")
})
}
}
Note: the 'Publish' version code is from a template in a tutorial. It had worked with a different URL.
What am I missing?
... or doing wrong?
Here's the data object for the JSON Decoder:
struct Coord: Codable {
let lon: Double
let lat: Double
}
struct Weather: Codable {
let id: Int
let main: String
let description: String
}
struct Wind: Codable {
let speed: Double
let deg: Int
}
struct Main: Codable {
let temp: Double
let pressure: Int
let humidity: Int
let tempMin: Double
let tempMax: Double
}
struct Sys: Codable {
let type: Int
let id: Int
let message: Double
let country: String
let sunrise: Int
let sunset: Int
}
struct Clouds: Codable {
let all: Int
}
struct Sample: Codable {
let coord: Coord
let weather: [Weather]
let base: String
let main: Main
let visibility: Int
let wind: Wind
let clouds: Clouds
let dt: Double
// let sys: Sys
let id: Int
let name: String
// let cod: Int
}