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

Swift:NSViewController与协议组合类型无法使用Equatable的问题

为什么类+协议组合类型无法使用Equatable?

在Swift 5.9中,定义如下协议与类:

protocol SpinnerHosting: AnyObject
{
    var spinnerItem: SpinnerItem { get }
}
final class MyViewController: NSViewController
{
    var activeChild: (NSViewController & SpinnerHosting)? = nil

    
    func pushChild(_ incomingChild: (NSViewController & SpinnerHosting))
    {
        // #1 报错:`Type 'any NSViewController & SpinnerHosting' cannot conform to 'Equatable'`
        if incomingChild != activeChild {
           ...
        }

        // #2 报错:`Binary operator '!=' cannot be applied to two 'any NSViewController & SpinnerHosting' operands`
        if incomingChild != activeChild! {
           ...
        }
    }
}

核心原因

虽然NSViewController本身遵循Equatable,且SpinnerHosting约束了AnyObject(引用类型本来可以靠指针判断相等),但这里的NSViewController & SpinnerHosting属于existential类型(也就是Swift 5.7+里的any类型),这类组合类型不会自动继承类的Equatable实现。

具体来说:

  • 当你用NSViewController & SpinnerHosting作为变量或参数类型时,Swift会把它当成一个容器,既包含NSViewController的所有特性,又满足SpinnerHosting的协议要求。
  • 哪怕底层类型是Equatable的类,existential类型本身需要明确声明遵循Equatable才能使用==或!=。但由于SpinnerHosting是协议,Swift没办法自动给这种类+协议的组合类型合成Equatable实现——它不会默认把类的Equatable实现“传递”给组合后的existential类型。

临时解决方法(针对引用相等需求)

如果你的需求只是判断两个对象是不是同一个实例(指针相等),可以直接用===操作符替代!=:

  • 针对#1的可选类型:
    if incomingChild !== activeChild {
        // ...
    }
    
  • 针对#2的解包后类型:
    if incomingChild !== activeChild! {
        // ...
    }
    

因为AnyObject约束的类型都支持===,刚好满足引用类型的相等判断需求。

内容的提问来源于stack exchange,提问作者Bryan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 05:07:16