Networking service is a http networking library developed on top of swift URLSession api. The library is capable of performing http network requests to REST api endpoints.
- ApiNetworkConfig
- RequestableEndpoint
- ApiEndpoint
- NetworkDataTransferService
- NetworkSessionManager
- NetworkLogger
- NetworkService
- etc.
This type is used to create an instance of the network configuration to start with. The type contains the below properties.
- baseUrl: URL - The base url of the api collection.
- headers: [String : String] - A dictionary containing key value pairs for the headers.
- queryParameters: [String : String] - A dictionary containing key value pairs for the query parameters which is used on the base url (if exists).
An enum containing the below cases,
- get
- head
- put
- update
- post
- delete
- patch
A protocol type which is used to handle response decoding. This contains the below methods,
- func decode<T: Decodable>(data: Data) throws -> T
This below types confirms to this abstract type.
- JsonResponseDecoder- Decodes the data as a Decodable object using a swift JsonDecoder
- RawDataResponseDecoder- Handles the raw data types such as images
A protocol type which is used to create blueprints of a endpoints. It contains the below properties and methods,
- var path: PathType {get}
- var method: HTTPMethodType {get}
- var headerParameters: [String: String] {get}
- var queryParameters: [String: Any] {get}
- var bodyParameters: [String: Any] {get}
- var responseDecoder: any ResponseDecoder {get}
- func urlRequest(with networkConfig: ApiNetworkConfig?) throws -> URLRequest
The ApiEndpoint is a concrete type which confirms to the RequestableEndpoint. When creating an instance of this type, make sure to provide a Decodable type for the Generic placeholder T.
Note: The PathType enum contains two cases (fullPath, path) with a associated String value for a url. The case fullPath is used when it's not a sub router path. The case path is used when it's a router path. ex: If the base url is https://666918ba2e964a6dfed3ced7.mockapi.io/users the Full path = https://666918ba2e964a6dfed3ced7.mockapi.io/users/all the Path = all
ex:
private var endpoint: ApiEndpoint<[ResponseObject]> {
return .init(path: .path("all"), method: .get, responseDecoder: JsonResponseDecoder())
}
ex:
private var endpoint: ApiEndpoint<[ResponseObject]> {
return .init(path: .fullPath("https://666918ba2e964a6dfed3ced7.mockapi.io/users/all"), method: .get, responseDecoder: JsonResponseDecoder())
}
- The method func urlRequest(....) will return a URLRequest instance which includes the query params, body params, http method and header parameters.
A protocol type which contains the below methods,
- func request(endpoint: any RequestableEndpoint, completion: @escaping CompletionHandler) -> CancellableHttpRequest?
- func request(_ request: URLRequest) async throws -> TaskType
The TaskType is a typealias which is a Task<(Data, URLResponse), Error>. This is a cancellable task which comes under the Swift's concurrency - async api.
Note: To call the async methods, it requires iOS 16 as a minimum target.
The DefaultNetworkSessionManager type confirms to the NetworkSessionManager protocol. It uses the iOS default session manager to execute the url requests.
A protocol type which contains the below methods,
- func request(endpoint: any RequestableEndpoint, completion: @escaping CompletionHandler) -> CancellableHttpRequest?
- func request(endpoint: any RequestableEndpoint) async -> TaskType
The TaskType is a typealias which is a Task<Data, Error>. This is a cancellable task which comes under the Swift's concurrency - async api.
The DefaultNetworkService type confirms to the NetworkService protocol. It is used to perform a http request using a http endpoint. The below methods are used to execute rewuests.
Method | Description |
---|---|
func request(endpoint: any RequestableEndpoint) async -> TaskType | This async method executes a request using the endpoint and returns a Task which will later be executed by the caller to get a result. |
func request(endpoint: any RequestableEndpoint, completion: @escaping CompletionHandler) -> (any CancellableHttpRequest)? | This method is used to execute a request using the provided endpoint and it will return a CancellableHttpRequest type which can be cancelled by the caller, using method cancel(). |
A protocol which contains the below methods,
- func log(request: URLRequest)
- func log(responseData data: Data?, response: URLResponse?)
- func log(error: Error)
The DefaultNetworkDataLogger is a concrete type which confirms to NetworkLogger. This is used to log the network call's requests, responses and errors.
A protocol type which contains the below methods,
-
func request<T: Decodable, E: RequestableEndpoint>(with endpoint: E, on queue: NetworkDataTransferQueue, completion: @escaping CompletionHandler ) -> CancellableHttpRequest? where E.ResponseType == T
-
func request<T: Decodable, E: RequestableEndpoint>(with endpoint: E, completion: @escaping CompletionHandler) -> CancellableHttpRequest? where E.ResponseType == T
-
func request<T: Decodable, E: RequestableEndpoint>(with endpoints: [E], on queue: NetworkDataTransferQueue, completion: @escaping CompletionHandlerCollection) -> CancellableHttpRequestCollection where E.ResponseType == T
-
func request<T: Decodable, E: RequestableEndpoint>(with endpoints: [E], completion: @escaping CompletionHandlerCollection) -> CancellableHttpRequestCollection where E.ResponseType == T
-
func request<T: Decodable, E: RequestableEndpoint>(with endpoint: E) async -> TaskType where E.ResponseType == T
-
func request<T: Decodable, E: RequestableEndpoint>(with endpoints: [E]) async -> TaskTypeCollection where E.ResponseType == T
The DefaultNetworkDataTransferService is a concrete type which confirms to the NetworkDataTransferService protocol. The class contains the below properties and these will be initialized through the designated initializer.
- networkService: NetworkService
- logger: NetworkDataTransferErrorLogger - this is a optional property, the default logger will be used, which uses OSLog api.
The below methods perform http requests through the provided network service and the response of type Data will be deserialized (converted) into the provided decodable types.
Method | Description |
---|---|
func request<T: Decodable, E: RequestableEndpoint>(with endpoint: E, on queue: NetworkDataTransferQueue, completion: @escaping CompletionHandler ) -> CancellableHttpRequest? where E.ResponseType == T | This method will execute the request and executes the completion handler on the provided DispatchQueue. |
func request<T: Decodable, E: RequestableEndpoint>(with endpoint: E, completion: @escaping CompletionHandler) -> CancellableHttpRequest? where E.ResponseType == T | This method will execute the request and executes the completion handler. |
func request<T: Decodable, E: RequestableEndpoint>(with endpoints: [E], on queue: NetworkDataTransferQueue, completion: @escaping CompletionHandlerCollection) -> CancellableHttpRequestCollection where E.ResponseType == T | This method will execute multiple http requests based on the provided url endpoints and executes the completion handler on the provided DispatchQueue. |
func request<T: Decodable, E: RequestableEndpoint>(with endpoints: [E], completion: @escaping CompletionHandlerCollection) -> CancellableHttpRequestCollection where E.ResponseType == T | This method will execute multiple http requests based on the provided endpoints and executes the completion handler. |
func request<T: Decodable, E: RequestableEndpoint>(with endpoint: E) async -> TaskType where E.ResponseType == T | This async method will return a task which can be later executed by the caller. This task can also be cancelled. |
func request<T: Decodable, E: RequestableEndpoint>(with endpoints: [E]) async -> TaskTypeCollection where E.ResponseType == T | This async method will return a parent task which can be later executed by the caller. This parent task can also be cancelled, which will result in cancelling all the child tasks. |
struct ResponseObject: Decodable {
let id: String
let avatar: String
let name: String
let createdAt: String
}
Creation of instances of below types,
- ApiNetworkConfig
- RequestableEndpoint
- NetworkService
- NetworkDataTransferService
private var networkConfig: ApiNetworkConfig {
let url = URL(string: "https://666918ba2e964a6dfed3ced7.mockapi.io/users")
return .init(baseUrl: url!)
}
private var endpoint: ApiEndpoint<[ResponseObject]> {
return .init(path: .path("all"), method: .get, responseDecoder: JsonResponseDecoder())
}
private var networkService: DefaultNetworkService {
return .init(networkConfig: networkConfig, sessionManagerType: .defaultType, loggerType: .defaultType)
}
private varnetworkDataTransferService: DefaultNetworkDataTransferService {
return .init(networkService: networkService, logger: DefaultNetworkDataTransferErrorLogger())
}
let cancellableRequest = networkDataTransferService.request(with: endpoint) { result in
switch result {
case .success(**let** data):
let items: [ResponseObject] = data
case .failure(**let** error):
print(error)
}
}
//Cancel request if no longer needed
cancellableRequest.cancel()
let task = await networkDataTransferService.request(with: endpoint)
do {
let items: [ResponseObject] = try await task.value
} catch {
print(error)
}