Swift 如何用一个错误类型提供本地化描述
Swift提供了一个协议来实现本地化描述。你可以使用 LocalizedError 协议来提供一个错误类型的本地化描述。这个协议可以通过结构、枚举或类来符合。采用这个协议后,你必须实现errorDescription属性以提供本地化描述。
下面是一个符合本地化错误协议的自定义错误枚举的例子:
创建一个自定义的错误并符合错误类型
在这个例子中,我们将创建一个名为CustomError的枚举,以符合LocalizedError协议。在这个枚举中,我们将添加案例来定义不同类型的错误。每个错误将代表一个不同的错误。下面是创建一个具有错误类型的枚举的例子:
例子
import Foundation
// An enum with different error types.
enum CustomError: Error {
case invalidUrl
case httpError
case timeoutError
case noConnectionError
case encodingError
case decodingError
case invalidResponseError
case unexpected(code: Int)
}
在上面的代码中,我们创建了一个名为CustomError的枚举,带有错误类型。同样的枚举,我们将用来符合不同的协议来进行本地化描述。
符合CustomStringConvertible协议
首先,我们将看到一个使用CustomStringConvertible协议的例子。使用这个,你可以为每种类型的错误提供一个自定义的消息。为了提供一个自定义的消息,你可以覆盖描述属性。
例子
下面是一个通过符合CustomStringConvertible协议来扩展CustomError枚举的例子:
// Assign an appropriate description to each type of error.
extension CustomError: CustomStringConvertible {
var description: String {
switch self {
case .invalidUrl:
return "There is a problem with a URL, such as an invalid URL or a timeout."
case .httpError:
return "There is an issue with an HTTP request or response."
case .timeoutError:
return "The request takes longer than the specified timeout period to complete."
case .noConnectionError:
return "There is no internet connection or the device is offline."
case .encodingError:
return "The data received from the server is unable to be encoded as the expected type."
case .decodingError:
return "The data received from the server is unable to be decoded as the expected type."
case .invalidResponseError:
return "The server responds with an unexpected format or status code."
case .unexpected(let code):
return "There is an unexpected error with the code \(code)"
}
}
}
使用LocalizedError为自定义错误添加本地化描述
在这一步,你将看到如何符合LocalizedError协议,为每个错误类型提供本地化的描述。一旦你符合LocalizedError协议,你可以覆盖errorDescription属性以提供本地化。
例子
下面是一个用本地化错误协议扩展CustomError枚举的例子。
// Assign a localized description to each type of error.
extension CustomError: LocalizedError {
var errorDescription: String? {
switch self {
case .invalidUrl:
return NSLocalizedString("There is a problem with a URL, such as an invalid URL or a timeout.", comment: "Invalid URL")
case .httpError:
return NSLocalizedString("There is an issue with an HTTP request or response.", comment: "HTTP Error")
case .timeoutError:
return NSLocalizedString("The request takes longer than the specified timeout period to complete.", comment: "Timeout Error")
case .noConnectionError:
return NSLocalizedString("There is no internet connection or the device is offline.", comment: "Internet Connection Error")
case .encodingError:
return NSLocalizedString("The data received from the server is unable to be encoded as the expected type.", comment: "Encoding Error")
case .decodingError:
return NSLocalizedString("The data received from the server is unable to be decoded as the expected type.", comment: "Decoding Error")
case .invalidResponseError:
return NSLocalizedString("The server responds with an unexpected format or status code.", comment: "Invalid Response Error")
case .unexpected(let code):
return NSLocalizedString("There is an unexpected error with the code \(code)", comment: "Unexpected Error")
}
}
}
扩展自定义错误
在Swift中,枚举具有更多的功能,可以让你扩展它的功能。你可以向枚举添加计算属性和函数。
我们将添加一个计算属性来确定错误是否是致命的类型。换句话说,我们将检查该错误是否可以被处理。比如说–
// Checking for unexpected errors that cannot be handled.
extension CustomError {
var isFatal: Bool {
if case CustomError.unexpected = self { return true }
else { return false }
}
}
实际用法
我们已经准备好了带有本地化描述的自定义错误。现在,让我们看看如何在你的项目中使用它们。
例子
func checkServerResponse(_ response: [String: Any]?) -> CustomError? {
// check for valid response
guard let responseDictionary = response else {
return CustomError.invalidResponseError
}
// check for valid status code
guard let statusCode = responseDictionary["statusCode"] as? Int,
statusCode >= 200 && statusCode <= 300 else {
return CustomError.unexpected(code: -1002)
}
// check for valid data object
guard let dataDictionary = responseDictionary["data"] as? [String: Any] else {
return CustomError.encodingError
}
print("Received Data: \(dataDictionary)")
return nil
}
let response: [String: Any] = ["statusCode": 201, "data": "user name"]
if let error = checkServerResponse(response) {
print("Error description: \(error.description)\nLocalized Description: \(error.localizedDescription)\nFatal Status: \(error.isFatal)")
}
输出
Error description: The data received from the server is unable to be encoded as the expected type.
Localized Description: The data received from the server is unable to be encoded as the expected type.
Fatal Status: false
在上面的例子中,我们创建了一个函数来检查从服务器收到的响应。如果发现任何错误,这个函数会返回一个自定义的可选类型的错误类型。
在函数的实现中,我们检查不同的有效情况。在每次检查时,如果有错误,就返回一个自定义的错误。
结论
在实际应用中,大部分时间你都在处理网络请求。很明显,你必须管理不同类型的错误。在Swift中,有一些协议是你可以遵守的,并扩展了用自定义消息或本地化描述来理解错误的能力。
CustomStringConvertible协议可以用来通过覆盖描述属性来提供自定义消息。你可以为每个错误类型提供有意义的消息。LocalizedError协议也可以用来提供一个错误类型的本地化描述。当一个错误发生时,使用这个功能来显示一个用户友好的信息是很好的做法。