it-roy-ru.com

Создайте свой собственный код ошибки в Swift 3

Я пытаюсь выполнить запрос 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!)
               }
          }
     }
}

Я не хочу обрабатывать условие ошибки в этой функции и хочу сгенерировать ошибку, используя код ответа, и вернуть эту ошибку, чтобы обработать ее везде, где вызывается эта функция. Кто-нибудь может сказать мне, как это сделать? Или это не «быстрый» способ справиться с такими ситуациями?

51
Rikh

В вашем случае ошибка заключается в том, что вы пытаетесь создать экземпляр Error. Error в Swift 3 - это протокол, который можно использовать для определения пользовательской ошибки. Эта функция особенно подходит для приложений на чистом Swift, работающих на разных ОС. 

В разработке для iOS класс NSError по-прежнему доступен и соответствует протоколу Error.

Таким образом, если ваша цель состоит только в распространении этого кода ошибки, вы можете легко заменить 

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

с

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

В противном случае проверьте Sandeep Bhandari s answer относительно того, как создать пользовательский тип ошибки

73
Luca D'Alberti

Вы можете создать протокол, соответствующий протоколу 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
    }
}
49
Harry Bloom

Вы можете создавать перечисления для устранения ошибок :)

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

У меня есть подробное руководство о том, как реструктурировать традиционную объектно-ориентированную сетевую модель, основанную на Objective-C, в современную модель, ориентированную на протокол, с использованием Swift3 здесь https://learnwithmehere.blogspot.in Посмотрите :)

Надеюсь, поможет :)

35
Sandeep Bhandari

Вы должны использовать объект NSError.

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

Затем приведите NSError к объекту Error. 

23
Ahmed Lotfy

Реализовать 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 приведет к строке «Операция не может быть завершена. (.StringError error 1.) "

13
prewett

Я знаю, что вы уже удовлетворились ответом, но если вы заинтересованы в правильном подходе, это может быть полезно для вас .... Я бы предпочел не смешивать код ошибки http-response с кодом ошибки в объекте error (в замешательстве? пожалуйста, продолжайте читать немного ...).

Коды ответов http - это стандартные коды ошибок для ответа http, определяющие общие ситуации, когда ответ принимается, и варьируются от 1xx до 5xx (например, 200 OK, 408 Тайм-аут запроса, 504 Тайм-аут шлюза и т.д. - http: //www.restapitutorial. com/httpstatuscodes.html )

Код ошибки в объекте NSError обеспечивает очень конкретную идентификацию для типа ошибки, которую объект описывает для конкретной области приложения/продукта/программного обеспечения. Например, ваше приложение может использовать 1000 для «Извините, вы не можете обновлять эту запись более одного раза в день» или сказать 1001 для «Вам нужна роль менеджера для доступа к этому ресурсу» ... которые относятся к вашему домену/приложению логика.

Для очень небольшого приложения иногда эти два понятия объединяются. Но они совершенно разные, как вы можете видеть, и очень важны и полезны для разработки и работы с большим программным обеспечением.

Таким образом, может быть два метода для лучшей обработки кода:

1. Завершение обратного вызова выполнит все проверки

completionHandler(data, httpResponse, responseError) 

2. Ваш метод решает ситуацию успеха и ошибки, а затем вызывает соответствующий обратный вызов

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

Удачного кодирования :)

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