Was ich zu erreichen versuche, ist, eine URLSession
-Anforderung in Swift 3 auszuführen. Ich führe diese Aktion in einer separaten Funktion aus (um den Code nicht separat für GET und POST zu schreiben) und die URLSessionDataTask
zurückgibt und den Erfolg und den Fehler in Schließungen behandelt . Art wie diese-
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!)
}
}
}
}
Ich möchte die Fehlerbedingung in dieser Funktion nicht behandeln und möchte mithilfe des Antwortcodes einen Fehler generieren und diesen Fehler zurückgeben, um ihn dort zu behandeln, wo auch immer diese Funktion aufgerufen wird. Kann mir jemand sagen, wie ich das machen soll? Oder ist dies nicht der "schnelle" Weg, um mit solchen Situationen umzugehen?
In Ihrem Fall ist der Fehler, dass Sie versuchen, eine Error
-Instanz zu generieren. Error
in Swift 3 ist ein Protokoll, mit dem ein benutzerdefinierter Fehler definiert werden kann. Diese Funktion ist insbesondere für reine Swift Anwendungen vorgesehen, die ausgeführt werden sollen auf verschiedenen Betriebssystemen.
In der iOS-Entwicklung ist die Klasse NSError
weiterhin verfügbar und entspricht dem Protokoll Error
.
Wenn Sie diesen Fehlercode nur verbreiten möchten, können Sie ihn problemlos ersetzen
var errorTemp = Error(domain:"", code:httpResponse.statusCode, userInfo:nil)
mit
var errorTemp = NSError(domain:"", code:httpResponse.statusCode, userInfo:nil)
Andernfalls überprüfen Sie die Sandeep Bhandari Antwort hinsichtlich der Erstellung eines benutzerdefinierten Fehlertyps
Sie können ein Protokoll erstellen, das dem Swift-Protokoll LocalizedError
entspricht, und zwar mit folgenden Werten:
protocol OurErrorProtocol: LocalizedError {
var title: String? { get }
var code: Int { get }
}
Dies ermöglicht uns dann, konkrete Fehler zu erzeugen:
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
}
}
Sie können Enums erstellen, um mit Fehlern umzugehen :)
enum RikhError: Error {
case unknownError
case connectionError
case invalidCredentials
case invalidRequest
case notFound
case invalidResponse
case serverError
case serverUnavailable
case timeOut
case unsuppotedURL
}
und dann eine Methode in enum erstellen, um den http-Antwortcode zu erhalten und den entsprechenden Fehler zurückzugeben :)
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
}
}
Aktualisieren Sie schließlich Ihren Fehlerblock, um einzelne Parameter des Typs RikhError zu akzeptieren :)
Ich habe ein ausführliches Tutorial zur Umstrukturierung des traditionellen Objective - C-basierten objektorientierten Netzwerkmodells auf ein modernes, protokollorientiertes Modell mit Swift3 hier https://learnwithmehere.blogspot.in Schauen Sie rein :)
Ich hoffe es hilft :)
Sie sollten das NSError-Objekt verwenden.
let error = NSError(domain:"", code:401, userInfo:[ NSLocalizedDescriptionKey: "Invalid access token"])
Umwandeln Sie dann NSError in Fehlerobjekt
Implementiere 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
}
}
Beachten Sie, dass das einfache Implementieren von Error, wie in einer der Antworten beschrieben, fehlschlägt (zumindest in Swift 3), und der Aufruf von localizedDescription führt zur Zeichenfolge "Die Operation konnte nicht abgeschlossen werden. (.StringError-Fehler 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)
}
Ich weiß, dass Sie mit einer Antwort bereits zufrieden sind, aber wenn Sie daran interessiert sind, den richtigen Ansatz zu kennen, kann dies für Sie hilfreich sein. Ich würde es vorziehen, den Fehlercode im Fehlerobjekt nicht mit dem Fehlercode zu kombinieren (verwirrt? bitte weiterlesen ...).
Die http-Antwortcodes sind Standardfehlercodes für eine http-Antwort, die generische Situationen definiert, in denen eine Antwort eingeht, und variieren von 1xx bis 5xx (z. B. 200 OK, 408 Zeitüberschreitung der Anforderung, 504 Gateway-Zeitüberschreitung usw.) - http: //www.restapitutorial. de/httpstatuscodes.html )
Der Fehlercode in einem NSError-Objekt liefert eine sehr genaue Identifikation der Art des Fehlers, den das Objekt für eine bestimmte Domäne einer Anwendung/eines Produkts/einer Software beschreibt. Beispielsweise verwendet Ihre Anwendung möglicherweise 1000 für "Tut mir leid, Sie können diesen Datensatz nicht mehr als einmal pro Tag aktualisieren" oder sagen Sie 1001 für "Sie benötigen eine Managerrolle, um auf diese Ressource zuzugreifen" ... die für Ihre Domäne/Anwendung spezifisch ist Logik.
Bei einer sehr kleinen Anwendung werden diese beiden Konzepte manchmal zusammengeführt. Sie sind jedoch ganz anders, wie Sie sehen können, und sehr wichtig und hilfreich beim Entwurf und der Arbeit mit umfangreicher Software.
Es gibt also zwei Techniken, um den Code besser zu handhaben:
completionHandler(data, httpResponse, responseError)
if nil == responseError {
successCallback(data)
} else {
failureCallback(data, responseError) // failure can have data also for standard REST request/response APIs
}
Viel Spaß beim Codieren :)
let error = NSError(domain:"", code:401, userInfo:[ NSLocalizedDescriptionKey: "Invaild UserName or Password"]) as Error
self.showLoginError(error)
erstellen Sie ein NSError-Objekt und geben Sie Error ein. Zeigen Sie es an einer beliebigen Stelle an
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)
}