/
NetworkClient.swift
89 lines (73 loc) · 3.36 KB
/
NetworkClient.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
77
78
79
80
81
82
83
84
85
86
87
88
89
//
// NetworkClient.swift
// HttpRequestWithRetry
//
// Created by Rob Kerr on 1/28/21.
//
import Foundation
class NetworkClient {
class var sharedInstance:NetworkClient {
struct SingletonWrapper {
static let singleton = NetworkClient()
}
return SingletonWrapper.singleton
}
let session = URLSession(configuration: URLSessionConfiguration.default, delegate: nil, delegateQueue: nil)
// MARK: - Fetching with retry
func fetchWithRetry(url: String, completion: @escaping (_ weather: Weather?, _ error: String?) -> Void) {
var request = URLRequest(url: URL(string: url)!)
request.httpMethod = "GET"
requestWithRetry(with: request) { (data, response, error, retriesLeft) in
if let error = error {
completion(nil, "\(error.localizedDescription) with \(retriesLeft) retries left")
return
}
let statusCode = (response as! HTTPURLResponse).statusCode
if statusCode == 200, let data = data {
let weather = try? JSONDecoder().decode(Weather.self, from: data)
completion(weather, nil)
} else {
completion(nil, "Error encountered: \(statusCode) with \(retriesLeft) retries left")
}
}
}
private func requestWithRetry(with request: URLRequest, retries: Int = 3,
completionHandler: @escaping (Data?, URLResponse?, Error?, _ retriesLeft: Int) -> Void) {
let task = session.dataTask(with: request) { (data, response, error) in
if error != nil {
completionHandler(data, response, error, retries)
return
}
let statusCode = (response as! HTTPURLResponse).statusCode
if (200...299).contains(statusCode) {
completionHandler(data, response, error, retries)
} else if retries > 0 {
print("Received status code \(statusCode) with \(retries) retries remaining. RETRYING VIA RECURSIVE CALL.")
self.requestWithRetry(with: request, retries: retries - 1, completionHandler: completionHandler)
} else {
print("Received status code \(statusCode) with \(retries) retries remaining. EXIT WITH FAILURE.")
completionHandler(data, response, error, retries)
}
}
task.resume()
}
// MARK: - Fetching without retry
func fetchWithoutRetry(url: String, completion: @escaping (_ weather: Weather?, _ error: String?) -> Void) {
var request = URLRequest(url: URL(string: url)!)
request.httpMethod = "GET"
let task = session.dataTask(with: request) { (data, response, error) in
let statusCode = (response as? HTTPURLResponse)?.statusCode ?? -1
if let error = error {
completion(nil, error.localizedDescription)
return
}
if (200...299).contains(statusCode), let data = data {
let weather = try? JSONDecoder().decode(Weather.self, from: data)
completion(weather, nil)
} else {
completion(nil, "Error encountered: \(statusCode)")
}
}
task.resume()
}
}