73 lines
2.3 KiB
Swift
73 lines
2.3 KiB
Swift
//
|
|
// NetworkService.swift
|
|
// EmployeeDirectory
|
|
//
|
|
// Created by Matt Bruce on 1/20/25.
|
|
//
|
|
|
|
import Foundation
|
|
|
|
public enum NetworkServiceError: Error {
|
|
/// The response from the server was invalid (e.g., non-200 status code or malformed URL).
|
|
case invalidResponse
|
|
|
|
/// The url giving is invalid or malformed
|
|
case invalidURL
|
|
|
|
/// The data received was invalid or could not be decoded.
|
|
case decodingError(DecodingError)
|
|
|
|
/// A network-related error occurred.
|
|
case networkError(URLError)
|
|
|
|
/// 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<T: Decodable>(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)
|
|
}
|
|
}
|
|
}
|