Xcode 9.3/Swift 4.1中无法创建仅限类的协议问题求助
解决Swift 4.1中弱引用存储协议类型的编译错误
这个问题是Swift 4.1(对应Xcode 9.3)的类型检查严格化导致的——虽然你的ThemeListener协议已经标记为继承AnyObject,但Swift现在要求明确区分协议类型和遵守该协议的类类型,而WeakRef<T>的约束T: AnyObject只接受类类型,不直接接受协议类型。
针对WeakRef的解决方法
你有两种简洁的修复方式:
方法1:调整类型别名,明确使用AnyObject & ThemeListener
修改你的类型别名,让它指向同时满足AnyObject和ThemeListener约束的类型,这样就能符合WeakRef的泛型要求:
class WeakRef<T> where T: AnyObject { private(set) weak var value: T? init(value: T?) { self.value = value } } protocol ThemeListener: AnyObject { } // 修改类型别名,明确约束 typealias WeakRefThemeListener = WeakRef<AnyObject & ThemeListener>
这样你创建实例时,传入任何遵守ThemeListener的类对象(比如UIView/UIViewController子类)都能正常工作,而且保持了WeakRef的通用性。
方法2:让WeakRef直接约束到ThemeListener
如果你的WeakRef只用来存储ThemeListener订阅者,可以直接修改WeakRef的泛型约束,这样类型别名就不需要额外处理:
// 直接约束T为遵守ThemeListener的类 class WeakRef<T: ThemeListener> where T: AnyObject { private(set) weak var value: T? init(value: T?) { self.value = value } } protocol ThemeListener: AnyObject { } typealias WeakRefThemeListener = WeakRef<ThemeListener>
针对NSHashTable的解决方法
NSHashTable的问题本质和WeakRef一致——它的泛型参数需要是AnyObject类型。你可以直接创建弱引用哈希表,存入对象时自动隐式转换,取出时再转回ThemeListener:
// 创建弱引用的哈希表 let listenerTable = NSHashTable<AnyObject>.weakObjects() // 添加订阅者(比如一个UIViewController子类实例) let viewController: SomeViewController = ... listenerTable.add(viewController) // 遍历订阅者时转换类型 for listener in listenerTable.allObjects.compactMap({ $0 as? ThemeListener }) { // 调用ThemeListener的方法 }
这样既保证了弱引用存储,又能正确处理协议类型的转换,避免内存泄漏。
内容的提问来源于stack exchange,提问作者Brett
相关产品推荐
相关产品推荐

