pods library eureka custom best ios swift3 nsurlsession

ios - library - Genere su propio código de error en Swift 3



swift libraries (9)

Lo que estoy tratando de lograr es realizar una solicitud URLSession en URLSession 3. Estoy realizando esta acción en una función separada (para no escribir el código por separado para GET y POST) y devolviendo URLSessionDataTask y manejando el éxito y el fracaso en los cierres . Algo así como

let task = URLSession.shared.dataTask(with: request) { (data, uRLResponse, responseError) in DispatchQueue.main.async { var httpResponse = uRLResponse as! HTTPURLResponse if responseError != nil && httpResponse.statusCode == 200{ successHandler(data!) }else{ if(responseError == nil){ //Trying to achieve something like below 2 lines //Following line throws an error soo its not possible //var errorTemp = Error(domain:"", code:httpResponse.statusCode, userInfo:nil) //failureHandler(errorTemp) }else{ failureHandler(responseError!) } } } }

No deseo manejar la condición de error en esta función y deseo generar un error usando el código de respuesta y devolver este error para manejarlo desde donde se llame esta función. ¿Alguien puede decirme cómo hacer esto? ¿O no es esta la forma "rápida" de manejar tales situaciones?


Detalles

  • Xcode versión 10.2.1 (10E1001)
  • Swift 5

Solución de errores de organización en una aplicación.

import Foundation enum AppError { case network(type: Enums.NetworkError) case file(type: Enums.FileError) case custom(errorDescription: String?) class Enums { } } extension AppError: LocalizedError { var errorDescription: String? { switch self { case .network(let type): return type.localizedDescription case .file(let type): return type.localizedDescription case .custom(let errorDescription): return errorDescription } } } // MARK: - Network Errors extension AppError.Enums { enum NetworkError { case parsing case notFound case custom(errorCode: Int?, errorDescription: String?) } } extension AppError.Enums.NetworkError: LocalizedError { var errorDescription: String? { switch self { case .parsing: return "Parsing error" case .notFound: return "URL Not Found" case .custom(_, let errorDescription): return errorDescription } } var errorCode: Int? { switch self { case .parsing: return nil case .notFound: return 404 case .custom(let errorCode, _): return errorCode } } } // MARK: - FIle Errors extension AppError.Enums { enum FileError { case read(path: String) case write(path: String, value: Any) case custom(errorDescription: String?) } } extension AppError.Enums.FileError: LocalizedError { var errorDescription: String? { switch self { case .read(let path): return "Could not read file from /"/(path)/"" case .write(let path, let value): return "Could not write value /"/(value)/" file from /"/(path)/"" case .custom(let errorDescription): return errorDescription } } }

Uso

//let err: Error = NSError(domain:"", code: 401, userInfo: [NSLocalizedDescriptionKey: "Invaild UserName or Password"]) let err: Error = AppError.network(type: .custom(errorCode: 400, errorDescription: "Bad request")) switch err { case is AppError: switch err as! AppError { case .network(let type): print("Network ERROR: code /(type.errorCode), description: /(type.localizedDescription)") case .file(let type): switch type { case .read: print("FILE Reading ERROR") case .write: print("FILE Writing ERROR") case .custom: print("FILE ERROR") } case .custom: print("Custom ERROR") } default: print(err) }


Debe usar el objeto NSError.

let error = NSError(domain:"", code:401, userInfo:[ NSLocalizedDescriptionKey: "Invalid access token"])

Luego envíe el objeto NSError to Error


En su caso, el error es que está intentando generar una instancia de Error . Error en Swift 3 es un protocolo que puede usarse para definir un error personalizado. Esta característica es especialmente para aplicaciones Swift puras que se ejecutan en diferentes sistemas operativos.

En el desarrollo de iOS, la clase NSError todavía está disponible y se ajusta al protocolo de Error .

Entonces, si su propósito es solo propagar este código de error, puede reemplazarlo fácilmente

var errorTemp = Error(domain:"", code:httpResponse.statusCode, userInfo:nil)

con

var errorTemp = NSError(domain:"", code:httpResponse.statusCode, userInfo:nil)

De lo contrario, verifique la answer Sandeep Bhandari sobre cómo crear un tipo de error personalizado


Implemente LocalizedError:

struct StringError : LocalizedError { var errorDescription: String? { return mMsg } var failureReason: String? { return mMsg } var recoverySuggestion: String? { return "" } var helpAnchor: String? { return "" } private var mMsg : String init(_ description: String) { mMsg = description } }

Tenga en cuenta que simplemente implementando Error, por ejemplo, como se describe en una de las respuestas, fallará (al menos en Swift 3), y llamar a localizedDescription dará como resultado la cadena "La operación no se pudo completar. (.StringError error 1.) "


Puede crear enumeraciones para tratar los errores :)

enum RikhError: Error { case unknownError case connectionError case invalidCredentials case invalidRequest case notFound case invalidResponse case serverError case serverUnavailable case timeOut case unsuppotedURL }

y luego cree un método dentro de enum para recibir el código de respuesta http y devolver el error correspondiente a cambio :)

static func checkErrorCode(_ errorCode: Int) -> RikhError { switch errorCode { case 400: return .invalidRequest case 401: return .invalidCredentials case 404: return .notFound //bla bla bla default: return .unknownError } }

Finalmente actualice su bloque de falla para aceptar un solo parámetro de tipo RikhError :)

Tengo un tutorial detallado sobre cómo reestructurar el modelo de red tradicional orientado a objetos basado en C a un modelo moderno orientado a protocolos usando Swift3 aquí https://learnwithmehere.blogspot.in Eche un vistazo :)

Espero eso ayude :)


Puede crear un protocolo, conforme al protocolo Swift LocalizedError , con estos valores:

protocol OurErrorProtocol: LocalizedError { var title: String? { get } var code: Int { get } }

Esto nos permite crear errores concretos de la siguiente manera:

struct CustomError: OurErrorProtocol { var title: String? var code: Int var errorDescription: String? { return _description } var failureReason: String? { return _description } private var _description: String init(title: String?, description: String, code: Int) { self.title = title ?? "Error" self._description = description self.code = code } }


Sé que ya está satisfecho con una respuesta, pero si está interesado en conocer el enfoque correcto, entonces esto podría ser útil para usted. Preferiría no mezclar el código de error de respuesta http con el código de error en el objeto de error (¿confundido? Continúe leyendo un poco ...).

Los códigos de respuesta http son códigos de error estándar sobre una respuesta http que define situaciones genéricas cuando se recibe la respuesta y varía de 1xx a 5xx (por ejemplo, 200 OK, 408 Tiempo de solicitud agotado, 504 Tiempo de espera de puerta de enlace, etc.) - http://www.restapitutorial.com/httpstatuscodes.html )

El código de error en un objeto NSError proporciona una identificación muy específica del tipo de error que el objeto describe para un dominio particular de aplicación / producto / software. Por ejemplo, su aplicación puede usar 1000 para "Lo sentimos, no puede actualizar este registro más de una vez en un día" o decir 1001 para "Necesita el rol de administrador para acceder a este recurso" ... que son específicos de su dominio / aplicación lógica.

Para una aplicación muy pequeña, a veces estos dos conceptos se fusionan. Pero, como puede ver, son completamente diferentes y muy importantes y útiles para diseñar y trabajar con software de gran tamaño.

Entonces, puede haber dos técnicas para manejar el código de una mejor manera:

1. La devolución de llamada de finalización realizará todas las verificaciones

completionHandler(data, httpResponse, responseError)

2. Su método decide la situación de éxito y error y luego invoca la devolución de llamada correspondiente

if nil == responseError { successCallback(data) } else { failureCallback(data, responseError) // failure can have data also for standard REST request/response APIs }

Feliz codificación :)


protocol CustomError : Error { var localizedTitle: String var localizedDescription: String } enum RequestError : Int, Error { case badRequest = 400 case loginFailed = 401 case userDisabled = 403 case notFound = 404 case methodNotAllowed = 405 case serverError = 500 case noConnection = -1009 case timeOutError = -1001 } func anything(errorCode: Int) -> CustomError? { return RequestError(rawValue: errorCode) }


let error = NSError(domain:"", code:401, userInfo:[ NSLocalizedDescriptionKey: "Invaild UserName or Password"]) as Error self.showLoginError(error)

cree un objeto NSError y escríbalo en Error, muéstrelo en cualquier lugar

private func showLoginError(_ error: Error?) { if let errorObj = error { UIAlertController.alert("Login Error", message: errorObj.localizedDescription).action("OK").presentOn(self) } }