-
Notifications
You must be signed in to change notification settings - Fork 15
/
Copy pathImageFetcher.swift
76 lines (61 loc) · 2.34 KB
/
ImageFetcher.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
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
//
// ImageFetcher.swift
// Example
//
// Created by Nacho Soto on 11/30/18.
// Copyright © 2018 Nacho Soto. All rights reserved.
//
import ReactiveSwift
import Result
public final class ImageFetcher {
private let urlSession: URLSession = {
let session = URLSession(configuration: URLSessionConfiguration.default)
return session
}()
private let decoder = JSONDecoder()
public init() {
precondition(!ImageFetcher.apiKey.isEmpty, "No API key was provided")
}
public func fetchImages(query: String) -> SignalProducer<[FlickrImageData], Error> {
func decodeJSON(data: Data) -> Result<Response, Error> {
return Result(try decoder.decode(Response.self, from: data))
.mapError(Error.invalidJSON)
}
return self.urlSession.reactive.data(with: self.requestForQuery(query))
.mapError(Error.networkError)
.map { data, _ in data } // ignore response
.attemptMap(decodeJSON)
.map { $0.photos.photo }
}
private func requestForQuery(_ query: String) -> URLRequest {
var components = URLComponents()
components.scheme = ImageFetcher.endpointScheme
components.host = ImageFetcher.endpointHost
components.path = ImageFetcher.endpointPath
components.queryItems = [
URLQueryItem(name: "method", value: "flickr.photos.search"),
URLQueryItem(name: "api_key", value: ImageFetcher.apiKey),
URLQueryItem(name: "format", value: ImageFetcher.format),
URLQueryItem(name: "nojsoncallback", value: "1"),
URLQueryItem(name: "text", value: query)
]
return URLRequest(url: components.url!)
}
// MARK: -
public enum Error: Swift.Error {
case networkError(originalError: AnyError)
case invalidJSON(originalError: AnyError)
}
// MARK: -
private static let endpointScheme: String = "https"
private static let endpointHost: String = "api.flickr.com"
private static let endpointPath: String = "/services/rest"
private static let apiKey: String = ""
private static let format: String = "json"
}
private struct Response: Decodable {
struct Photos: Decodable {
let photo: [FlickrImageData]
}
let photos: Photos
}