Skip to content
Snippets Groups Projects
Commit 184d1fd4 authored by Tobias Ullerich's avatar Tobias Ullerich
Browse files

Add async method for data requests

parent 8f372876
Branches
No related tags found
No related merge requests found
......@@ -519,6 +519,7 @@
"@executable_path/Frameworks",
"@loader_path/Frameworks",
);
MARKETING_VERSION = 1.1;
PRODUCT_BUNDLE_IDENTIFIER = de.tobias.AppleLibs;
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
SKIP_INSTALL = YES;
......@@ -546,6 +547,7 @@
"@executable_path/Frameworks",
"@loader_path/Frameworks",
);
MARKETING_VERSION = 1.1;
PRODUCT_BUNDLE_IDENTIFIER = de.tobias.AppleLibs;
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
SKIP_INSTALL = YES;
......
......@@ -15,7 +15,7 @@
<key>CFBundlePackageType</key>
<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<string>$(MARKETING_VERSION)</string>
<key>CFBundleVersion</key>
<string>$(CURRENT_PROJECT_VERSION)</string>
</dict>
......
......@@ -12,12 +12,12 @@ import os.log
public protocol HttpResponseFilter
{
func handleResponse(request: Request, data: Data?, responseHandler: ResponseHandler?, sender: Any?, promise: Promise<Data?, ResponseError>)
func handleResponse(request: Request, data: Data?, responseHandler: ResponseHandler?, sender: Any?) throws -> Any?
}
public protocol HttpSuccessFilter
{
func handleResponse(data: Data?, response: HTTPURLResponse, responseHandler: ResponseHandler?, sender: Any?, promise: Promise<Data?, ResponseError>)
func handleResponse(data: Data?, response: HTTPURLResponse, responseHandler: ResponseHandler?, sender: Any?) throws -> Any?
}
public protocol DataManagerDelegate
......@@ -91,8 +91,8 @@ public class DataManager: NSObject, URLSessionDelegate
public func request(request r: Request,
responseHandler: ResponseHandler? = nil,
sender: Any? = nil,
promise: Promise<Data?, ResponseError> = Promise<Data?, ResponseError>())
-> Future<Data?, ResponseError> {
promise: Promise<Any?, ResponseError> = Promise<Any?, ResponseError>())
-> Future<Any?, ResponseError> {
if #available(iOS 14.0, *) {
os_log("Request: \(r)")
} else {
......@@ -101,13 +101,9 @@ public class DataManager: NSObject, URLSessionDelegate
let request = delegate?.manipulateRequest(request: r) ?? r
if var req: URLRequest = createUrlRequest(request: request) {
if let authentication = request.authentication {
if let headerKey = authentication.headerKey, let headerValue = authentication.headerValue {
req.setValue(headerValue, forHTTPHeaderField: headerKey)
}
guard let req: URLRequest = createUrlRequest(request: request) else {
return promise.future
}
let task = urlSession.dataTask(with: req) { data, response, error in
if let error: NSError = error as NSError? {
promise.fail(error: self.determineResponseError(error))
......@@ -119,19 +115,60 @@ public class DataManager: NSObject, URLSessionDelegate
return
}
do {
if response.is2xx {
self.responseOkFilter.handleResponse(data: data, response: response, responseHandler: responseHandler, sender: sender, promise: promise)
let result = try self.responseOkFilter.handleResponse(data: data, response: response, responseHandler: responseHandler, sender: sender)
promise.succeed(value: result)
} else if let filter = self.responseFilters[response.statusCode] {
filter.handleResponse(request: request, data: data, responseHandler: responseHandler, sender: sender, promise: promise)
try filter.handleResponse(request: request, data: data, responseHandler: responseHandler, sender: sender)
} else {
promise.fail(error: ResponseError.getErrorForStatusCode(code: response.statusCode))
}
} catch {
promise.fail(error: ResponseError.clientError(error: error))
}
task.resume()
}
task.resume()
return promise.future
}
@available(iOS 15.0, *)
@available(macCatalyst 15.0.0, *)
@discardableResult
public func request(request r: Request, responseHandler: ResponseHandler? = nil, sender: Any? = nil) async throws -> Any? {
os_log("Request: \(r)")
let request = delegate?.manipulateRequest(request: r) ?? r
guard let req: URLRequest = createUrlRequest(request: request) else {
throw ResponseError.requestError
}
let (data, response): (Data, URLResponse)
do {
(data, response) = try await urlSession.data(for: req)
} catch {
throw self.determineResponseError(error)
}
guard let response: HTTPURLResponse = response as? HTTPURLResponse else {
throw ResponseError.networkError(error: .unknown())
}
do {
if response.is2xx {
return try self.responseOkFilter.handleResponse(data: data, response: response, responseHandler: responseHandler, sender: sender)
} else if let filter = self.responseFilters[response.statusCode] {
return try filter.handleResponse(request: request, data: data, responseHandler: responseHandler, sender: sender)
} else {
throw ResponseError.getErrorForStatusCode(code: response.statusCode)
}
} catch {
throw error
}
}
private func createUrlRequest(request: Request) -> URLRequest? {
if let url: URL = request.constructUrl() {
var req: URLRequest = URLRequest(url: url)
......@@ -144,19 +181,25 @@ public class DataManager: NSObject, URLSessionDelegate
}
req.timeoutInterval = self.timeout
if let authentication = request.authentication {
if let headerKey = authentication.headerKey, let headerValue = authentication.headerValue {
req.setValue(headerValue, forHTTPHeaderField: headerKey)
}
}
return req
}
return nil
}
fileprivate func determineResponseError(_ error: NSError) -> ResponseError {
fileprivate func determineResponseError(_ error: Error) -> ResponseError {
let error = error as NSError
if error.code == NSURLErrorNotConnectedToInternet {
return ResponseError.networkError(error: .noInternet)
} else if error.code == NSURLErrorTimedOut {
return ResponseError.networkError(error: .timeout)
} else {
return ResponseError.networkError(error: .unknown(error: error))
}
return ResponseError.networkError(error: .unknown(error: error))
}
public func urlSession(_ session: URLSession, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
......
......@@ -31,6 +31,7 @@ public enum ResponseError: Error
case internalError
}
case requestError
case authError(error: AuthError)
case httpError(error: HttpError)
case networkError(error: NetworkError)
......
......@@ -10,5 +10,5 @@ import Foundation
public protocol ResponseHandler
{
func handleResponse(data: Data?, response: URLResponse?, sender: Any?) throws
func handleResponse(data: Data?, response: URLResponse?, sender: Any?) throws -> Any?
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment