Подтвердить что ты не робот

Создайте свой собственный код ошибки в 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!)
               }
          }
     }
}

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

4b9b3361

Ответ 1

В вашем случае ошибка заключается в том, что вы пытаетесь создать экземпляр 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 о том, как создать собственный тип ошибки

Ответ 2

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

Ответ 3

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

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 Посмотрите:)

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

Ответ 4

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

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

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

Ответ 5

Реализация 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 1.)"

Ответ 6

подробности

  • Версия Xcode 10.2.1 (10E1001)
  • Swift 5

Решение по организации ошибок в приложении

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

Ответ 7

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

Ответ 8

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

Коды ответов 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
}

Счастливое кодирование:)

Ответ 9

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