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

问题描述 投票:59回答:8

我想要实现的是在swift 3中执行URLSession请求。我在一个单独的函数中执行此操作(以便不为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!)
               }
          }
     }
}

我不希望处理此函数中的错误条件,并希望使用响应代码生成错误,并返回此错误以在任何调用此函数的位置处理它。任何人都可以告诉我该怎么做?或者这不是处理这种情况的“快速”方式吗?

ios swift3 nsurlsession
8个回答
82
投票

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

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

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

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

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

否则,请检查Sandeep Bhandari的answer,了解如何创建自定义错误类型


57
投票

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

protocol OurErrorProtocol: LocalizedError {

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

这使我们能够创建具体的错误:

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

38
投票

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

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

然后在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
        }
    }

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

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

希望能帮助到你 :)


27
投票

您应该使用NSError对象。

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

然后将NSError转换为Error对象


14
投票

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

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


1
投票

我知道你已经对答案感到满意,但如果你有兴趣知道正确的方法,那么这可能对你有所帮助。我宁愿不将http响应错误代码与错误对象中的错误代码混合(混淆?请继续阅读...)。

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

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

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

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

1. The completion callback will perform all the checks

completionHandler(data, httpResponse, responseError) 

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

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

快乐编码:)


1
投票
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)
}

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

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

private func showLoginError(_ error: Error?) {
    if let errorObj = error {
        UIAlertController.alert("Login Error", message: errorObj.localizedDescription).action("OK").presentOn(self)
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.