Ce que j'essaie de réaliser, c'est d'exécuter une URLSession
requête 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) et je renvoie URLSessionDataTask
et gère 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 en utilisant le code de réponse et renvoyer cette erreur pour la gérer partout où cette fonction est appelée. Quelqu'un peut-il me dire comment procéder? Ou n'est-ce pas la manière «Swift» de gérer de telles situations?
ios
swift3
nsurlsession
Rikh
la source
la source
NSError
au lieu deError
dans la déclaration (var errorTemp = NSError(...)
)Error
protocoleRéponses:
Vous pouvez créer un protocole, conforme au
LocalizedError
protocole Swift , avec ces valeurs:protocol OurErrorProtocol: LocalizedError { var title: String? { get } var code: Int { get } }
Cela nous permet alors 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 } }
la source
Dans votre cas, l'erreur est que vous essayez de générer une
Error
instance.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 à exécuter sur différents systèmes d'exploitation.Dans le développement iOS, la
NSError
classe est toujours disponible et elle est conforme auError
protocole.Donc, si votre but est uniquement 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érifier le Sandeep Bhandari de » réponse sur la façon de créer un type d'erreur personnalisé
la source
Error cannot be created because it has no accessible initializers
.Error
, maisNSError
. Bien sûr, l'utilisationError
génère une erreur.Vous pouvez créer des énumérations 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 à l'intérieur de 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 traditionnel basé sur Objective-C en un modèle moderne orienté protocole en utilisant Swift3 ici https://learnwithmehere.blogspot.in Jetez un oeil :)
J'espère que cela aide :)
la source
Vous devez utiliser l'objet NSError.
let error = NSError(domain:"", code:401, userInfo:[ NSLocalizedDescriptionKey: "Invalid access token"])
Puis cast NSError en objet Error
la source
Détails
Solution des erreurs d'organisation dans une application
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 } } }
Usage
//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) }
la source
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 simplement implémenter Error, par exemple, comme décrit dans l'une des réponses, échouera (au moins dans Swift 3) et que l'appel de localizedDescription entraînera la chaîne "L'opération n'a pas pu être terminée. (.StringError error 1.) "
la source
struct StringError : LocalizedError { public let errorDescription: String? }
, et utiliser simplement commeStringError(errorDescription: "some message")
let error = NSError(domain:"", code:401, userInfo:[ NSLocalizedDescriptionKey: "Invaild UserName or Password"]) as Error self.showLoginError(error)
créer un objet NSError et le convertir en erreur, l'afficher n'importe où
private func showLoginError(_ error: Error?) { if let errorObj = error { UIAlertController.alert("Login Error", message: errorObj.localizedDescription).action("OK").presentOn(self) } }
la source
Je pense toujours que la réponse de Harry est la plus simple et la plus complète, mais si vous avez besoin de quelque chose d'encore plus simple, utilisez:
struct AppError { let message: String init(message: String) { self.message = message } } extension AppError: LocalizedError { var errorDescription: String? { return message } // var failureReason: String? { get } // var recoverySuggestion: String? { get } // var helpAnchor: String? { get } }
Et utilisez ou testez-le comme ceci:
printError(error: AppError(message: "My App Error!!!")) func print(error: Error) { print("We have an ERROR: ", error.localizedDescription) }
la source
protocol CustomError : Error { var localizedTitle: String var localizedDescription: String } enum RequestError : Int, CustomError { 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) }
la source
Je sais que vous êtes déjà satisfait d'une réponse, mais si vous souhaitez connaître la bonne approche, cela pourrait vous être utile. Je préférerais ne pas mélanger le code d'erreur de réponse http avec le code d'erreur dans l'objet d'erreur (confus? Veuillez continuer à lire un peu ...).
Les codes de réponse http sont des codes d'erreur standard concernant une réponse http définissant des situations génériques lorsque la réponse est reçue et varie de 1xx à 5xx (par exemple 200 OK, 408 Request timed out, 504 Gateway timeout 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 dire 1001 pour "Vous avez besoin du rôle de gestionnaire pour accéder à cette ressource" ... qui sont spécifiques à votre domaine / application logique.
Pour une toute petite application, ces deux concepts sont parfois fusionnés. Mais ils sont complètement différents comme vous pouvez le voir et très importants et utiles pour concevoir et travailler avec de gros logiciels.
Donc, il peut y avoir deux techniques pour mieux gérer le code:
1. Le rappel de fin exécutera toutes les vérifications
2. Votre méthode décide du succès et de la situation d'erreur, puis appelle le rappel correspondant
if nil == responseError { successCallback(data) } else { failureCallback(data, responseError) // failure can have data also for standard REST request/response APIs }
Bon codage :)
la source