如何在Swift中使用Error类型提供本地化的描述?


Swift 提供了一个协议来实现本地化描述。您可以使用 `LocalizedError` 协议来提供错误类型的本地化描述。结构体、枚举或类都可以遵循此协议。采用此协议后,您必须实现 `errorDescription` 属性来提供本地化描述。

这是一个遵循 `LocalizedError` 协议的自定义错误枚举示例:

创建一个自定义错误并符合 `Error` 类型

在这个例子中,我们将创建一个名为 `CustomError` 的枚举来符合 `LocalizedError` 协议。在枚举中,我们将添加 case 来定义不同类型的错误。每个错误都将代表一个不同的错误。以下是如何创建一个带有 `Error` 类型的枚举的示例:

示例

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` 并带有 `Error` 类型的枚举。我们将使用相同的枚举来符合不同的协议以本地化描述。

符合 `CustomStringConvertible` 协议

首先,我们将看到一个使用 `CustomStringConvertible` 协议的示例。使用它,您可以为每种类型的错误提供自定义消息。要提供自定义消息,您可以覆盖 `description` 属性。

示例

这是一个通过符合 `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` 为自定义错误添加 `localizedDescription`

在此步骤中,您将看到如何符合 `LocalizedError` 协议以针对每种错误类型提供本地化描述。一旦您符合 `LocalizedError` 协议,您可以覆盖 `errorDescription` 属性来提供本地化。

示例

这是一个使用 `LocalizedError` 协议扩展 `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` 协议通过覆盖 `description` 属性来提供自定义消息。您可以为每种错误类型提供有意义的消息。`LocalizedError` 协议也可以用来提供错误类型的本地化描述。当发生错误时,使用此功能显示用户友好的消息是一个好习惯。

更新于:2023年2月28日

3K+ 次浏览

启动您的职业生涯

完成课程获得认证

开始学习
广告