Я пытаюсь выполнить URLSession
запрос в быстром 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!)
}
}
}
}
Я не хочу обрабатывать состояние ошибки в этой функции и хочу сгенерировать ошибку, используя код ответа, и вернуть эту ошибку, чтобы обработать ее, откуда бы эта функция ни вызывалась. Кто-нибудь может сказать мне, как это сделать? Или это не «быстрый» способ справляться с такими ситуациями?
NSError
вместоError
в объявлении (var errorTemp = NSError(...)
)Error
протоколОтветы:
Вы можете создать протокол, соответствующий
LocalizedError
протоколу Swift , со следующими значениями: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 } }
источник
В вашем случае ошибка в том, что вы пытаетесь создать
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 ответ о том , как создать пользовательский тип ошибки
источник
Error cannot be created because it has no accessible initializers
.Error
, ноNSError
. Конечно, использованиеError
вызывает ошибку.Вы можете создавать перечисления для устранения ошибок :)
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 Посмотрите :)
Надеюсь, это поможет :)
источник
Вы должны использовать объект NSError.
let error = NSError(domain:"", code:401, userInfo:[ NSLocalizedDescriptionKey: "Invalid access token"])
Затем приведите NSError к объекту ошибки
источник
Детали
Решение ошибок организации в приложении
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) }
источник
Реализуйте 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.) "
источник
struct StringError : LocalizedError { public let errorDescription: String? }
, а это просто использовать какStringError(errorDescription: "some message")
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) } }
источник
Я все еще думаю, что ответ Гарри самый простой и законченный, но если вам нужно что-то еще более простое, используйте:
struct AppError { let message: String init(message: String) { self.message = message } } extension AppError: LocalizedError { var errorDescription: String? { return message } // var failureReason: String? { get } // var recoverySuggestion: String? { get } // var helpAnchor: String? { get } }
И используйте или протестируйте это так:
printError(error: AppError(message: "My App Error!!!")) func print(error: Error) { print("We have an ERROR: ", error.localizedDescription) }
источник
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) }
источник
Я знаю, что вы уже удовлетворены ответом, но если вам интересно узнать правильный подход, это может быть вам полезно. Я бы предпочел не смешивать код ошибки http-ответа с кодом ошибки в объекте ошибки (запутались? Продолжите читать немного ...).
Коды HTTP-ответа - это стандартные коды ошибок HTTP-ответа, определяющие общие ситуации получения ответа, и варьируются от 1xx до 5xx (например, 200 OK, 408 Request timed out, 504 Gateway timeout и т. Д. - http://www.restapitutorial.com/ httpstatuscodes.html )
Код ошибки в объекте NSError обеспечивает очень конкретную идентификацию типа ошибки, которую объект описывает для конкретной области приложения / продукта / программного обеспечения. Например, ваше приложение может использовать 1000 для «Извините, вы не можете обновлять эту запись более одного раза в день» или скажите 1001 для «Вам нужна роль менеджера для доступа к этому ресурсу» ... которые относятся к вашему домену / приложению. логика.
Для очень небольшого приложения иногда эти две концепции объединяются. Но они совершенно разные, как видите, и очень важны и полезны для проектирования и работы с большим программным обеспечением.
Итак, есть два метода для лучшей обработки кода:
1. Обратный вызов завершения выполнит все проверки.
2. Ваш метод определяет успешную или ошибочную ситуацию, а затем вызывает соответствующий обратный вызов.
if nil == responseError { successCallback(data) } else { failureCallback(data, responseError) // failure can have data also for standard REST request/response APIs }
Удачного кодирования :)
источник