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

Swift 4.1中类专属协议作为关联类型别名的兼容问题求解

解决Swift 4.1中StringManager不遵守ObserversHolder协议的问题

这个问题我之前也碰到过,本质是Swift 4.1对关联类型的约束检查做了严格升级,咱们一步步来拆解:

问题根源

你的ObserversHolder协议要求关联类型ObserverValue必须是AnyObject(也就是类类型),但你在StringManager里把ObserverValue指定为StringObserver——这是个仅允许类遵循的协议,而非具体的类。在Swift 4.0里,类型检查没有严格区分这两者,所以能混过去;但Swift 4.1开始明确了:仅类遵循的协议本身不算AnyObject类型,因此触发了不遵守协议的报错。

两种可行的修复方案

方案1:修改协议的关联类型约束

直接把ObserversHolder里ObserverValue的约束从AnyObject改成class,这样协议就允许关联类型是类或者仅类遵循的协议,完美适配你的场景:

protocol ObserversHolder {
    associatedtype ObserverValue: class
    var observers: [ObserverValue] { get set }
}

protocol StringObserver: class {
    func showString()
}

class StringManager: ObserversHolder {
    typealias ObserverValue = StringObserver
    var observers = [ObserverValue]()
}

方案2:用具体类替代协议作为关联类型

如果你想保留ObserversHolder的AnyObject约束,可以先定义一个遵循StringObserver的基类,再把ObserverValue指向这个类:

protocol ObserversHolder {
    associatedtype ObserverValue: AnyObject
    var observers: [ObserverValue] { get set }
}

protocol StringObserver: class {
    func showString()
}

// 定义一个基类实现StringObserver协议
class BaseStringObserver: StringObserver {
    func showString() {
        // 这里可以写默认实现,或者留空让子类重写
    }
}

class StringManager: ObserversHolder {
    typealias ObserverValue = BaseStringObserver
    var observers = [ObserverValue]()
}

之后你的具体观察者类只需要继承BaseStringObserver就行,完全满足AnyObject的约束要求。

额外说明

Swift团队在4.1版本里修复了类型系统的一个模糊点,之前允许仅类遵循的协议被当作AnyObject处理,现在这个漏洞被补上了,所以才出现了这个兼容性问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 06:49:39