Ce que j'essaie de faire est d'exécuter une requête URLSession
dans Swift 3. J'effectue cette action dans une fonction distincte (afin de ne pas écrire le code séparément pour GET et POST), de retourner la URLSessionDataTask
et de gérer le succès et l'échec des fermetures . Un peu comme ça-
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!)
}
}
}
}
Je ne souhaite pas gérer la condition d'erreur dans cette fonction et souhaite générer une erreur à l'aide du code de réponse et renvoyer cette erreur pour qu'elle soit traitée quelle que soit l'origine de cette fonction. Quelqu'un peut-il me dire comment s'y prendre? Ou n'est-ce pas le moyen "rapide" de gérer de telles situations?
Dans votre cas, l'erreur est que vous essayez de générer une instance Error
. Error
dans Swift 3 est un protocole qui peut être utilisé pour définir une erreur personnalisée. Cette fonctionnalité est spécialement conçue pour les applications Swift pures s'exécutant sous différents systèmes d'exploitation
Dans le développement iOS, la classe NSError
est toujours disponible et conforme au protocole Error
.
Donc, si votre but est seulement de propager ce code d'erreur, vous pouvez facilement remplacer
var errorTemp = Error(domain:"", code:httpResponse.statusCode, userInfo:nil)
avec
var errorTemp = NSError(domain:"", code:httpResponse.statusCode, userInfo:nil)
Sinon, vérifiez le réponse de Sandeep Bhandari concernant la création d'un type d'erreur personnalisé.
Vous pouvez créer un protocole conforme au protocole Swift LocalizedError
avec les valeurs suivantes:
protocol OurErrorProtocol: LocalizedError {
var title: String? { get }
var code: Int { get }
}
Cela nous permet ensuite de créer des erreurs concrètes comme ceci:
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
}
}
Vous pouvez créer des enums pour traiter les erreurs :)
enum RikhError: Error {
case unknownError
case connectionError
case invalidCredentials
case invalidRequest
case notFound
case invalidResponse
case serverError
case serverUnavailable
case timeOut
case unsuppotedURL
}
puis créez une méthode dans enum pour recevoir le code de réponse http et renvoyer l'erreur correspondante en retour :)
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
}
}
Enfin, mettez à jour votre bloc d’échec pour accepter un seul paramètre de type RikhError :)
J'ai un tutoriel détaillé sur la façon de restructurer le modèle de réseau orienté objet basé sur Objective - C basé sur le modèle moderne orienté protocole utilisant Swift3 ici https://learnwithmehere.blogspot.in Regardez :)
J'espère que ça aide :)
Implémentez 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
}
}
Notez que la simple implémentation de Error, par exemple, comme décrit dans l’une des réponses, échouera (du moins dans Swift 3) et que l’appel de localizedDescription entraînera la chaîne "L’opération n’a pas pu aboutir. (Erreur 1.StringError 1.) "
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
}
}
}
//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)
}
Je sais que vous êtes déjà satisfait d'une réponse, mais si vous êtes intéressé à connaître la bonne approche, cela pourrait vous être utile ... Je préférerais ne pas mélanger le code d'erreur http-response avec le code d'erreur dans l'objet error (confus? S'il vous plaît continuer à lire un peu ...).
Les codes de réponse http sont des codes d'erreur standard relatifs à une réponse http définissant des situations génériques lors de la réception d'une réponse. Ils varient de 1xx à 5xx (par exemple, 200 OK, 408 demandes expirées, 504 Timeout de la passerelle, etc. - http: //www.restapitutorial .com/httpstatuscodes.html )
Le code d'erreur dans un objet NSError fournit une identification très spécifique du type d'erreur décrit par l'objet pour un domaine particulier d'application/produit/logiciel. Par exemple, votre application peut utiliser 1000 pour "Désolé, vous ne pouvez pas mettre à jour cet enregistrement plus d'une fois par jour" ou 1001 pour "Vous avez besoin du rôle de responsable pour accéder à cette ressource" ... spécifiques à votre domaine/application. logique.
Pour une très petite application, ces deux concepts sont parfois fusionnés. Mais comme vous pouvez le constater, ils sont complètement différents et très importants et utiles pour concevoir et utiliser de gros logiciels.
Donc, il peut y avoir deux techniques pour mieux gérer le code:
completionHandler(data, httpResponse, responseError)
if nil == responseError {
successCallback(data)
} else {
failureCallback(data, responseError) // failure can have data also for standard REST request/response APIs
}
Bonne codage :)
let error = NSError(domain:"", code:401, userInfo:[ NSLocalizedDescriptionKey: "Invaild UserName or Password"]) as Error
self.showLoginError(error)
créer un objet NSError et le transtyper en Error, le montrer n'importe où
private func showLoginError(_ error: Error?) {
if let errorObj = error {
UIAlertController.alert("Login Error", message: errorObj.localizedDescription).action("OK").presentOn(self)
}
}
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)
}