Swift中是否有更优的错误比较方式?(自定义AuthenticationError场景)
解决Swift中AuthenticationError枚举的相等性比较问题
我来给你捋捋这个问题的解决思路和具体代码实现。因为Swift的Error协议本身并没有继承Equatable,所以直接比较Error和自定义的AuthenticationError确实需要额外处理,但我们可以通过让枚举遵循Equatable+重载跨类型运算符的方式,避免重复写冗余的_code和_domain比较逻辑。
第一步:让AuthenticationError遵循Equatable
首先我们要让自定义错误枚举实现Equatable协议,这样它自身实例的相等性比较就有了基础。不过因为其中webRequestFailed的关联值是Error(非Equatable类型),所以我们需要手动实现==方法:
public enum AuthenticationError: Error, Equatable { case unknownError case canceledByUser case userOrPasswordMismatch case unableToExtractOneTimeCode case unableToExchangeOneTimeCodeForToken case credentialsUnavailable case expired case webRequestFailed(error: Error) public static func == (lhs: Self, rhs: Self) -> Bool { switch (lhs, rhs) { // 匹配所有无关联值的case,直接返回相等 case (.unknownError, .unknownError), (.canceledByUser, .canceledByUser), (.userOrPasswordMismatch, .userOrPasswordMismatch), (.unableToExtractOneTimeCode, .unableToExtractOneTimeCode), (.unableToExchangeOneTimeCodeForToken, .unableToExchangeOneTimeCodeForToken), (.credentialsUnavailable, .credentialsUnavailable), (.expired, .expired): return true // 处理带关联值的case:用Error的_domain和_code判断相等 case (.webRequestFailed(let lhsError), .webRequestFailed(let rhsError)): return lhsError._domain == rhsError._domain && lhsError._code == rhsError._code // 其他不匹配的情况返回不相等 default: return false } } }
第二步:重载跨类型的==运算符
当你需要把Error类型的实例和AuthenticationError实例比较时(比如某个方法返回Error,你要判断是不是我们自定义的错误),需要重载两个方向的==运算符,通过类型转换来复用上面的Equatable实现:
// 处理 Error == AuthenticationError 的情况 public func == (lhs: Error, rhs: AuthenticationError) -> Bool { // 先尝试把Error转成AuthenticationError,成功后用已实现的==比较 guard let lhsAuthError = lhs as? AuthenticationError else { return false } return lhsAuthError == rhs } // 处理 AuthenticationError == Error 的情况 public func == (lhs: AuthenticationError, rhs: Error) -> Bool { // 同理,把Error转成AuthenticationError后比较 guard let rhsAuthError = rhs as? AuthenticationError else { return false } return lhs == rhsAuthError }
为什么这样做?
- 避免了重复编写
_code和_domain的比较逻辑,所有核心的相等性判断都集中在枚举自身的==方法里,维护起来更方便。 - 跨类型的比较通过类型转换实现,逻辑清晰,只要是
AuthenticationError的实例,不管被装箱成Error还是保持原类型,都能正确比较。
内容的提问来源于stack exchange,提问作者Jason Leach
相关产品推荐
相关产品推荐

