forked from zmfrew/synchronous-combine
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Contents.swift
59 lines (48 loc) · 1.71 KB
/
Contents.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
import Combine
import Foundation
struct ApiClient {
func make<T: Decodable>(
_ request: URLRequest,
_ decoder: JSONDecoder = JSONDecoder()
) -> AnyPublisher<T, Error> {
URLSession.shared
.dataTaskPublisher(for: request)
.map(\.data)
.decode(type: T.self, decoder: decoder)
.receive(on: DispatchQueue.main)
.eraseToAnyPublisher()
}
}
struct WeatherProvider {
let apiClient: ApiClient
private let base = URL(string: "https://www.metaweather.com/api/")!
func woeid(
latitude: Double,
longitude: Double
) -> AnyPublisher<[Location], Error> {
let url = base.appendingPathComponent("location/search/")
var components = URLComponents(url: url, resolvingAgainstBaseURL: true)!
components.queryItems = [
URLQueryItem(
name: "lattlong",
value: "\(latitude),\(longitude)"
)
]
let request = URLRequest(url: components.url!)
return apiClient.make(request)
}
func weather(woeid: Int) -> AnyPublisher<WeatherResponse, Error> {
let request = URLRequest(url: base.appendingPathComponent("location/\(woeid)"))
return apiClient.make(request)
}
}
let weatherProvider = WeatherProvider(apiClient: ApiClient())
let woeidSubscriber = weatherProvider.woeid(latitude: 38.6255, longitude: -90.1861)
let firstLocation = woeidSubscriber.compactMap({ $0.first })
let weatherResponse = firstLocation.flatMap { location in
weatherProvider.weather(woeid: location.woeid)
}
let cancellationToken = weatherResponse.sink(
receiveCompletion: { _ in },
receiveValue: { print($0.weather) }
)