Skip to content

Commit 0332130

Browse files
author
burak.uzunboy
committed
New API Configuration with custom error models
1 parent 4222e61 commit 0332130

7 files changed

Lines changed: 293 additions & 130 deletions

File tree

Sources/UsefulNetworkLayer/Extensions/UIImage+ResponseImage.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
// Copyright © 2020 BUZ. All rights reserved.
77
//
88

9+
#if !os(macOS)
910
import UIKit
1011

1112
/**
@@ -20,7 +21,7 @@ public extension UIImage {
2021

2122
api.request { (result) in
2223
switch result {
23-
case .error(_):
24+
case .failure(_):
2425
completion(nil)
2526
case .success(let response):
2627
completion(response.responseBody.image)
@@ -48,3 +49,4 @@ public extension UIImage {
4849

4950
}
5051

52+
#endif

Sources/UsefulNetworkLayer/Extensions/UIImageView+ImageURL.swift

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
// Copyright © 2020 BUZ. All rights reserved.
77
//
88

9+
#if !os(macOS)
910
import UIKit
1011

1112
public extension UIImageView {
@@ -59,17 +60,17 @@ public extension UIImageView {
5960
activityIndicator.centerXAnchor.constraint(equalTo: self.centerXAnchor).isActive = true
6061
activityIndicator.centerYAnchor.constraint(equalTo: self.centerYAnchor).isActive = true
6162

62-
let request = APIConfiguration(url: url,
63-
responseBodyObject: ResponseImage.self,
64-
priority: .high, timeOut: 10)
63+
let request = APIConfiguration<ResponseImage, DefaultAPIError>(url: url,
64+
responseBodyObject: ResponseImage.self,
65+
priority: .high, timeOut: 10)
6566

6667
request.request { (result) in
6768
DispatchQueue.main.async { [weak self] in
6869
guard let self = self else { return }
6970
activityIndicator.removeFromSuperview()
7071
switch result {
71-
case .error(let error):
72-
errorCompletion?(error.error)
72+
case .failure(let error):
73+
errorCompletion?(error.errorReason.error! as NSError)
7374
if let fallback = fallback {
7475
self.image = fallback
7576
}
@@ -119,3 +120,4 @@ public struct ResponseImage: ResponseBodyParsable {
119120

120121
}
121122

123+
#endif

Sources/UsefulNetworkLayer/NetworkLayer/APIConfiguration.swift

Lines changed: 114 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ import Foundation
2424
import CoreUsefulSDK
2525

2626
/// Structure that keeps all information needed from Network Layer for operations.
27-
public struct APIConfiguration<T> where T: ResponseBodyParsable {
27+
public struct APIConfiguration<T,S> where T: ResponseBodyParsable, S: ErrorResponseParsable {
2828
/// Returns `URL` of the API request.
2929
public var requestURL: URL
3030

@@ -40,6 +40,9 @@ public struct APIConfiguration<T> where T: ResponseBodyParsable {
4040
/// The expected object type from the request.
4141
public var responseBodyObject: T.Type
4242

43+
/// The expected object type for the errors.
44+
public var errorResponseBodyObject: S.Type
45+
4346
/// `NetworkLayer` priorities the API request by looking that parameter.
4447
public var priority: Operation.QueuePriority
4548

@@ -54,7 +57,7 @@ public struct APIConfiguration<T> where T: ResponseBodyParsable {
5457

5558
/// The timeout value for the request wait time.
5659
public var timeOut: Int
57-
60+
5861
/**
5962
Initializes Configuration with the host URL and endpoint separately.
6063
Returns nil if request URL cannot be created successfuly.
@@ -72,30 +75,32 @@ public struct APIConfiguration<T> where T: ResponseBodyParsable {
7275
Then specified custom caching will be applied for that request.
7376
*/
7477
public init?(hostURL: String, endPoint: String,
75-
requestType: NetworkLayer.RequestType = .get,
76-
headers: [String:String]? = nil,
77-
body: [String:Any]? = nil,
78-
responseBodyObject: T.Type,
79-
priority: Operation.QueuePriority = Operation.QueuePriority.normal,
80-
cachingTime: NetworkLayer.CachingTime = NetworkLayer.CachingTime(seconds: 60 * 60),
81-
isMainOperation: Bool = false,
82-
autoCache: Bool = false,
83-
timeOut: Int = 30) {
78+
requestType: NetworkLayer.RequestType = .get,
79+
headers: [String:String]? = nil,
80+
body: [String:Any]? = nil,
81+
responseBodyObject: T.Type,
82+
errorType: S.Type,
83+
priority: Operation.QueuePriority = Operation.QueuePriority.normal,
84+
cachingTime: NetworkLayer.CachingTime = NetworkLayer.CachingTime(seconds: 60 * 60),
85+
isMainOperation: Bool = false,
86+
autoCache: Bool = false,
87+
timeOut: Int = 30) {
8488

8589
var url = URL(string: hostURL)
8690
url?.appendPathComponent(endPoint)
8791
guard let requestURL = url else { return nil }
8892

89-
self.requestURL = requestURL
90-
self.requestType = requestType
91-
self.headers = headers
92-
self.body = body
93-
self.responseBodyObject = responseBodyObject
94-
self.priority = priority
95-
self.cachingTime = cachingTime
96-
self.isMainOperation = isMainOperation
97-
self.autoCache = autoCache
98-
self.timeOut = timeOut
93+
self.init(url: requestURL,
94+
requestType: requestType,
95+
headers: headers,
96+
body: body,
97+
responseBodyObject: responseBodyObject,
98+
errorType: errorType,
99+
priority: priority,
100+
cachingTime: cachingTime,
101+
isMainOperation: isMainOperation,
102+
autoCache: autoCache,
103+
timeOut: timeOut)
99104
}
100105

101106
/**
@@ -113,15 +118,16 @@ public struct APIConfiguration<T> where T: ResponseBodyParsable {
113118
Then specified custom caching will be applied for that request.
114119
*/
115120
public init(url: URL,
116-
requestType: NetworkLayer.RequestType = .get,
117-
headers: [String:String]? = nil,
118-
body: [String:Any]? = nil,
119-
responseBodyObject: T.Type,
120-
priority: Operation.QueuePriority = .normal,
121-
cachingTime: NetworkLayer.CachingTime = NetworkLayer.CachingTime(seconds: 60 * 60),
122-
isMainOperation: Bool = false,
123-
autoCache: Bool = false,
124-
timeOut: Int = 30) {
121+
requestType: NetworkLayer.RequestType = .get,
122+
headers: [String:String]? = nil,
123+
body: [String:Any]? = nil,
124+
responseBodyObject: T.Type,
125+
errorType: S.Type,
126+
priority: Operation.QueuePriority = .normal,
127+
cachingTime: NetworkLayer.CachingTime = NetworkLayer.CachingTime(seconds: 60 * 60),
128+
isMainOperation: Bool = false,
129+
autoCache: Bool = false,
130+
timeOut: Int = 30) {
125131

126132
self.requestURL = url
127133
self.requestType = requestType
@@ -133,6 +139,7 @@ public struct APIConfiguration<T> where T: ResponseBodyParsable {
133139
self.isMainOperation = isMainOperation
134140
self.autoCache = autoCache
135141
self.timeOut = timeOut
142+
self.errorResponseBodyObject = errorType
136143
}
137144

138145
/// Tries to create URL request by specified parameters.
@@ -175,69 +182,90 @@ public struct APIConfiguration<T> where T: ResponseBodyParsable {
175182
/// Requests given API configuration by using `NetworkLayer`.
176183
/// - Parameter completion: Completion block which contains error or success case.
177184
/// - Parameter response: Response `Enum` which has two cases, whether `error` or `success`.
178-
public func request(completion: @escaping (_ response: NetworkLayer.Result<T>)->()) {
185+
public func request(completion: @escaping (_ response: NetworkLayer.Result<T,S>)->()) {
179186
NetworkLayer.execute(self, completion: completion)
180187
}
181188

182189
}
183190

184-
/**
185-
The response objects should be inherited from the `ResponseBodyParsable` to operate by the `NetworkLayer`.
186-
*/
187-
public protocol ResponseBodyParsable: Codable, NameDescribeable {
188-
/// To allow `NetworkLayer` to use defined initializer, set `true`, otherwise `Codable` protocol will be used.
189-
static var shouldUseCustomInitializer: Bool { get }
190-
/// Use this initializer to allow custom parsing from JSON object.
191-
init?(response: Any?)
192-
/// Use this initializer to allow custom parsing from Data directly.
193-
init?(data: Data)
194-
/// If custom value is defined, Caching will use this method to detect expiry.
195-
func cachingEndsAt() -> Date?
196-
}
197-
198-
public extension ResponseBodyParsable {
199-
init?(response: Any?) { return nil }
200-
init?(data: Data) { return nil }
201-
func cachingEndsAt() -> Date? { return nil }
202-
static var shouldUseCustomInitializer: Bool { return false }
203-
}
204-
205-
extension Array: NameDescribeable where Element: NameDescribeable {
206-
207-
}
208-
209-
extension Array: ResponseBodyParsable where Element: ResponseBodyParsable {
210-
211-
}
212-
213-
/// Response of the API if request is completed successfully.
214-
public struct APIResponse<T> where T: ResponseBodyParsable {
215-
216-
/// Response body of the API request.
217-
public private(set) var responseBody: T
218-
219-
/// Main URL response of the API request.
220-
public private(set) var response: URLResponse
191+
public extension APIConfiguration where T: ResponseBodyParsable, S == DefaultAPIError {
221192

222-
internal init(response: URLResponse, responseBody: T) {
223-
self.response = response
224-
self.responseBody = responseBody
193+
/**
194+
Initializes Configuration with the host URL and endpoint separately. Initializes `DefaultAPIError` if any error occurs.
195+
Returns nil if request URL cannot be created successfuly.
196+
- parameter hostURL: Base URL for the request. (e.g. "https://example.com")
197+
- parameter endPoint: Endpoint for the API request. (e.g. "v1/api/test")
198+
- parameter priority: Defines the priority of the operation in its queue.
199+
- parameter timeOut: Timeout value for the request to fail if it cannot get answer from network in seconds. In default, it's 30 seconds.
200+
- parameter cachingTime: Default caching time for the response, in default it's 1 hour.
201+
- parameter requestType: Type of the request. In default it's `get`.
202+
- parameter isMainOperation: If `true`, operation will be performed in special queue and return to main queue.
203+
- parameter headers: Headers for the API request. Don't need to add `content-Type` for JSON request bodies, which will be automatically added.
204+
- parameter body: Request body for the API request.
205+
- parameter responseBodyObject: Type of the Response Object to create.
206+
- parameter autoCache: To use that, override `cachingEndsAt:` method of Response Body Object.
207+
Then specified custom caching will be applied for that request.
208+
*/
209+
init?(hostURL: String, endPoint: String,
210+
requestType: NetworkLayer.RequestType = .get,
211+
headers: [String:String]? = nil,
212+
body: [String:Any]? = nil,
213+
responseBodyObject: T.Type,
214+
priority: Operation.QueuePriority = Operation.QueuePriority.normal,
215+
cachingTime: NetworkLayer.CachingTime = NetworkLayer.CachingTime(seconds: 60 * 60),
216+
isMainOperation: Bool = false,
217+
autoCache: Bool = false,
218+
timeOut: Int = 30) {
219+
220+
self.init(hostURL: hostURL,
221+
endPoint: endPoint,
222+
requestType: requestType,
223+
headers: headers,
224+
body: body,
225+
responseBodyObject: responseBodyObject,
226+
errorType: DefaultAPIError.self,
227+
priority: priority,
228+
cachingTime: cachingTime,
229+
isMainOperation: isMainOperation,
230+
autoCache: autoCache,
231+
timeOut: timeOut)
225232
}
226233

227-
}
228-
229-
/// Error result if the API request fails.
230-
public struct APIError<T> where T: ResponseBodyParsable {
231-
232-
/// Error reason that explains why API request is failed.
233-
public private(set) var error: NSError
234-
235-
/// The API request that fails.
236-
public private(set) var api: APIConfiguration<T>
237-
238-
internal init(request: APIConfiguration<T>, error: NSError) {
239-
self.api = request
240-
self.error = error
234+
/**
235+
Initializes Configuration with the URL and initializes `DefaultAPIError` if any error occurs.
236+
- parameter url: Request URL.
237+
- parameter priority: Defines the priority of the operation in its queue.
238+
- parameter timeOut: Timeout value for the request to fail if it cannot get answer from network in seconds. In default, it's 30 seconds.
239+
- parameter cachingTime: Default caching time for the response, in default it's 1 hour.
240+
- parameter requestType: Type of the request. In default it's `get`.
241+
- parameter isMainOperation: If `true`, operation will be performed in special queue and return to main queue.
242+
- parameter headers: Headers for the API request. Don't need to add `content-Type` for JSON request bodies, which will be automatically added.
243+
- parameter body: Request body for the API request.
244+
- parameter responseBodyObject: Type of the Response Object to create.
245+
- parameter autoCache: To use that, override `cachingEndsAt:` method of Response Body Object.
246+
Then specified custom caching will be applied for that request.
247+
*/
248+
init(url: URL,
249+
requestType: NetworkLayer.RequestType = .get,
250+
headers: [String:String]? = nil,
251+
body: [String:Any]? = nil,
252+
responseBodyObject: T.Type,
253+
priority: Operation.QueuePriority = .normal,
254+
cachingTime: NetworkLayer.CachingTime = NetworkLayer.CachingTime(seconds: 60 * 60),
255+
isMainOperation: Bool = false,
256+
autoCache: Bool = false,
257+
timeOut: Int = 30) {
258+
259+
self.init(url: url,
260+
requestType: requestType,
261+
headers: headers,
262+
body: body,
263+
responseBodyObject: responseBodyObject,
264+
errorType: DefaultAPIError.self,
265+
priority: priority,
266+
cachingTime: cachingTime,
267+
isMainOperation: isMainOperation,
268+
autoCache: autoCache,
269+
timeOut: timeOut)
241270
}
242-
243271
}

0 commit comments

Comments
 (0)