webentwicklung-frage-antwort-db.com.de

Generieren Sie Ihren eigenen Fehlercode in Swift 3

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?

51
Rikh

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

84
Luca D'Alberti

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
    }
}
49
Harry Bloom

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 :)

35

Sie sollten das NSError-Objekt verwenden.

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

Umwandeln Sie dann NSError in Fehlerobjekt

28
Ahmed Lotfy

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.) "

13
prewett

Einzelheiten

  • Xcode Version 10.2.1 (10E1001)
  • Swift 5

Lösung für das Organisieren von Fehlern in einer App

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
        }
    }
}

Verwendungszweck

//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)
}
5

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:

1. Der Beendigungsrückruf führt alle Prüfungen aus

completionHandler(data, httpResponse, responseError) 

2. Ihre Methode entscheidet über die Erfolgs- und Fehlersituation und ruft dann den entsprechenden Rückruf auf

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

Viel Spaß beim Codieren :)

1
Tushar
 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)
    }
}
1
Suraj K Thomas
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)
}
0
Daniel.scheibe