ios 在 swift 3 中生成您自己的错误代码

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/40671991/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-31 10:49:33  来源:igfitidea点击:

Generate your own Error code in swift 3

iosswift3nsurlsession

提问by Rikh

What I am trying to achieve is perform a URLSessionrequest in swift 3. I am performing this action in a separate function (so as not to write the code separately for GET and POST) and returning the URLSessionDataTaskand handling the success and failure in closures. Sort of like this-

我想要实现的是URLSession在 swift 3 中执行请求。我在单独的函数中执行此操作(以免为 GET 和 POST 分别编写代码)并返回URLSessionDataTask并处理闭包中的成功和失败。有点像这样——

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

I do not wish to handle the error condition in this function and wish to generate an error using the response code and return this Error to handle it wherever this function is called from. Can anybody tell me how to go about this? Or is this not the "Swift" way to go about handling such situations?

我不希望处理此函数中的错误条件,并希望使用响应代码生成错误并返回此错误以在调用此函数的任何地方处理它。谁能告诉我如何解决这个问题?或者这不是处理这种情况的“Swift”方式吗?

采纳答案by Harry Bloom

You can create a protocol, conforming to the Swift LocalizedErrorprotocol, with these values:

您可以LocalizedError使用以下值创建符合 Swift协议的协议:

protocol OurErrorProtocol: LocalizedError {

    var title: String? { get }
    var code: Int { get }
}

This then enables us to create concrete errors like so:

这使我们能够创建具体的错误,如下所示:

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

回答by Luca D'Alberti

In your case, the error is that you're trying to generate an Errorinstance. Errorin Swift 3 is a protocol that can be used to define a custom error. This feature is especially for pure Swift applications to run on different OS.

在您的情况下,错误是您正在尝试生成一个Error实例。Error在 Swift 3 中是一个可用于定义自定义错误的协议。此功能特别适用于在不同操作系统上运行的纯 Swift 应用程序。

In iOS development the NSErrorclass is still available and it conforms to Errorprotocol.

在 iOS 开发中,NSError该类仍然可用,并且符合Error协议。

So, if your purpose is only to propagate this error code, you can easily replace

因此,如果您的目的只是传播此错误代码,则可以轻松替换

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

with

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

Otherwise check the Sandeep Bhandari's answerregarding how to create a custom error type

否则检查Sandeep Bhandari的关于如何创建自定义错误类型的答案

回答by Sandeep Bhandari

You can create enums to deal with errors :)

您可以创建枚举来处理错误:)

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

and then create a method inside enum to receive the http response code and return the corresponding error in return :)

然后在enum里面创建一个方法来接收http响应码并返回相应的错误返回:)

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

Finally update your failure block to accept single parameter of type RikhError :)

最后更新您的故障块以接受 RikhError 类型的单个参数:)

I have a detailed tutorial on how to restructure traditional Objective - C based Object Oriented network model to modern Protocol Oriented model using Swift3 here https://learnwithmehere.blogspot.inHave a look :)

我有一个关于如何使用 Swift3 将传统的基于 Objective-C 的面向对象的网络模型重构为现代面向协议的模型的详细教程https://learnwithmehere.blogspot.in看看:)

Hope it helps :)

希望能帮助到你 :)

回答by Ahmed Lotfy

You should use NSError object.

您应该使用 NSError 对象。

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

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

Then cast NSError to Error object

然后将 NSError 转换为 Error 对象

回答by Vasily Bodnarchuk

Details

细节

  • Xcode Version 10.2.1 (10E1001)
  • Swift 5
  • Xcode 版本 10.2.1 (10E1001)
  • 斯威夫特 5

Solution of organizing errors in an 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
        }
    }
}

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

回答by prewett

Implement LocalizedError:

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

Note that simply implementing Error, for instance, as described in one of the answers, will fail (at least in Swift 3), and calling localizedDescription will result in the string "The operation could not be completed. (.StringError error 1.)"

请注意,例如,如答案之一中所述,简单地实现 Error 将失败(至少在 Swift 3 中),并且调用 localizedDescription 将导致字符串“操作无法完成。(.StringError 错误 1。) ”

回答by Suraj K Thomas

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

create an NSError object and typecast it to Error ,show it anywhere

创建一个 NSError 对象并将其类型转换为 Error ,在任何地方显示它

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

回答by Daniel.scheibe

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

回答by Tushar

I know you have already satisfied with an answer but if you are interested to know the right approach, then this might be helpful for you. I would prefer not to mix http-response error code with the error code in the error object (confused? please continue reading a bit...).

我知道您已经对答案感到满意,但如果您有兴趣了解正确的方法,那么这可能对您有所帮助。我不希望将 http-response 错误代码与错误对象中的错误代码混合在一起(困惑?请继续阅读……)。

The http response codes are standard error codes about a http response defining generic situations when response is received and varies from 1xx to 5xx ( e.g 200 OK, 408 Request timed out,504 Gateway timeout etc - http://www.restapitutorial.com/httpstatuscodes.html)

http 响应代码是关于 http 响应的标准错误代码,定义接收响应时的一般情况,从 1xx 到 5xx(例如 200 OK、408 请求超时、504 网关超时等 - http://www.restapitutorial.com/ httpstatuscodes.html)

The error code in a NSError object provides very specific identification to the kind of error the object describes for a particular domain of application/product/software. For example your application may use 1000 for "Sorry, You can't update this record more than once in a day" or say 1001 for "You need manager role to access this resource"... which are specific to your domain/application logic.

NSError 对象中的错误代码为该对象为应用程序/产品/软件的特定领域描述的错误类型提供了非常具体的标识。例如,您的应用程序可能使用 1000 表示“抱歉,您不能在一天内多次更新此记录”,或者使用 1001 表示“您需要管理员角色才能访问此资源”...这些特定于您的域/应用程序逻辑。

For a very small application, sometimes these two concepts are merged. But they are completely different as you can see and very important & helpful to design and work with large software.

对于非常小的应用程序,有时会合并这两个概念。但是正如您所看到的,它们完全不同,并且对于设计和使用大型软件非常重要和有帮助。

So, there can be two techniques to handle the code in better way:

因此,可以有两种技术以更好的方式处理代码:

1. The completion callback will perform all the checks

1. 完成回调将执行所有检查

completionHandler(data, httpResponse, responseError) 

2. Your method decides success and error situation and then invokes corresponding callback

2.你的方法决定成功和错误的情况,然后调用相应的回调

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

Happy coding :)

快乐编码:)