From 255356ff19bcd550ffbad06681b86bc8df35b07d Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Mon, 20 Jan 2025 17:05:20 -0600 Subject: [PATCH] created singleton to just fetch data for a decodable. this doesn't handle any customization for a URLRequest, just dealing with a public url for now. Signed-off-by: Matt Bruce --- .../Services/NetworkService.swift | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/EmployeeDirectory/Services/NetworkService.swift b/EmployeeDirectory/Services/NetworkService.swift index 5fb1366..80582dd 100644 --- a/EmployeeDirectory/Services/NetworkService.swift +++ b/EmployeeDirectory/Services/NetworkService.swift @@ -23,3 +23,50 @@ public enum NetworkServiceError: Error { /// An unexpected, uncategorized error occurred. case unknownError(Error) } + +public class NetworkService { + + public static let shared = NetworkService() // Default shared instance + + private let session: URLSession + + /// Public initializer to allow customization + public init(session: URLSession = .shared) { + self.session = session + } + + /// Fetches data from a URL and decodes it into a generic Decodable type. + /// - Parameters: + /// - endpoint: The url to fetch data from. + /// - type: The type to decode the data into. + /// - Throws: A `ServiceError` for network, decoding, or unexpected errors. + /// - Returns: The decoded object of the specified type. + public func fetchData(from endpoint: String, as type: T.Type) async throws -> T { + do { + //ensure a valid URL + guard let url = URL(string: endpoint) else { + throw NetworkServiceError.invalidURL + } + + // Perform network request + let (data, response) = try await URLSession.shared.data(for: URLRequest(url: url)) + + // Validate HTTP response + guard let httpResponse = response as? HTTPURLResponse, httpResponse.statusCode == 200 else { + throw NetworkServiceError.invalidResponse + } + + // Decode the response into the specified type + return try JSONDecoder().decode(T.self, from: data) + + } catch let urlError as URLError { + throw NetworkServiceError.networkError(urlError) + + } catch let decodingError as DecodingError { + throw NetworkServiceError.decodingError(decodingError) + + } catch { + throw NetworkServiceError.unknownError(error) + } + } +}