You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 07:51:51