// // NetworkManager.swift // WOKA // // Created by MacBook Pro on 06/05/24. // import Alamofire class NetworkManager{ static let shareInstance = NetworkManager() private let alamofireLogger = AlamofireLogger() private init() {} enum APIError: Error { case networkError case noNetwork(message:String) case invalidURL case parameterEncodingFailed case responseValidationFailed case unknown(message: String) case custom(message: String) } /// This function will do the network call for HTTPMethod & Encoding is URLEncoding with contentType ["application/json"] /// /// /// - Warning: The returned string is not localized. /// /// Usage: /// /// Alamofire network call Generic (.get , .post, .put.). /// /// - Parameter (header : HTTPHeaders , Params :[String : Any] , URL , Dedocable Generic T Struct. , queue : dispatchQueue decide) /// - NOTE Oncompletion will be called on main thread so no need to specify the main thread for UI updates /// - Returns: This function returns a GENERIC response base on the T Model & APIError . func apiRequest( url: URLConvertible, method: HTTPMethod, parameters: Parameters? = nil, encoding: ParameterEncoding = URLEncoding.default, headers: HTTPHeaders? = nil, queue: DispatchQueue = QueueHelper.background, completionHandler: @escaping (Result) -> Void ) { // Stop monitoring network reachability NetworkReachibility.shared.stopMonitoring() // Execute the request on the specified queue queue.async { AF.request(url, method: method, parameters: parameters, encoding: encoding, headers: headers, requestModifier: { $0.timeoutInterval = 30 }) .authenticate(username: "admin", password: "Woka@1234") .validate(statusCode: 200..<300) .responseDecodable(of: T.self) { response in // alamofireLogger.request(response.da, didParseResponse: response) switch response.result { case .success(let value): // Handle successful response on the main thread DispatchQueue.main.async { completionHandler(.success(value)) } case .failure(let error): // Handle failure cases if let afError = error as? AFError { switch afError { case .sessionTaskFailed(let urlError): if urlError._code == -1020 || urlError._code == -1009 { // Handle network error on the main thread DispatchQueue.main.async { completionHandler(.failure(.noNetwork(message: K.ConstantString.noInternet))) } } else { // Handle other network errors on the main thread DispatchQueue.main.async { completionHandler(.failure(.networkError)) } } case .invalidURL: // Handle invalid URL error on the main thread DispatchQueue.main.async { completionHandler(.failure(.invalidURL)) } case .parameterEncodingFailed: // Handle parameter encoding failure on the main thread DispatchQueue.main.async { completionHandler(.failure(.parameterEncodingFailed)) } case .responseValidationFailed: // Handle response validation failure on the main thread DispatchQueue.main.async { completionHandler(.failure(.responseValidationFailed)) } default: // Handle other network errors on the main thread DispatchQueue.main.async { completionHandler(.failure(.networkError)) } } } else { // Handle unrecognized errors on the main thread DispatchQueue.main.async { completionHandler(.failure(.unknown(message: K.ConstantString.unRecognised))) } } } } } } } final class AlamofireLogger: EventMonitor { func requestDidResume(_ request: Request) { let allHeaders = request.request.flatMap { $0.allHTTPHeaderFields.map { $0.description } } ?? "None" let headers = """ ⚡️⚡️⚡️⚡️ Request Started: \(request) ⚡️⚡️⚡️⚡️ Headers: \(allHeaders) """ NSLog(headers) let body = request.request.flatMap { $0.httpBody.map { String(decoding: $0, as: UTF8.self) } } ?? "None" let message = """ ⚡️⚡️⚡️⚡️ Request Started: \(request) ⚡️⚡️⚡️⚡️ Body Data: \(body) """ NSLog(message) } func request(_ request: DataRequest, didParseResponse response: AFDataResponse) { NSLog("⚡️⚡️⚡️⚡️ Response Received: \(response.debugDescription)") NSLog("⚡️⚡️⚡️⚡️ Response All Headers: \(String(describing: response.response?.allHeaderFields))") } }