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
相关产品推荐
相关产品推荐

