Swift泛型存储UIView&协议组合类型弱引用报错求解
问题根源
这是Swift泛型系统的已知限制:当泛型参数带有类约束(例如你写的Type: AnyObject)时,编译器不会将类+协议组合的存在类型判定为满足类约束。哪怕逻辑上UIView & commonFunctions必然是类类型,也无法通过泛型的类型校验——这就是为什么你直接声明weak var var1: (UIView & commonFunctions)?完全合法,但把同个类型作为泛型参数传入就报错的原因。
你提到的@objc协议方案不可行是符合预期的:@objc协议不支持元组、Swift原生值类型等成员,你的协议里overrideMargins是元组类型,确实无法标记为@objc。
解决方案
方案1:专用类型包装(优先选择)
如果你的字典仅用来存储UIView & commonFunctions类型的对象,不需要通用泛型能力,直接定义对应类型的弱引用包装即可,零运行时风险,类型安全最高:
class WeakCommonViewWrapper { weak var value: (UIView & commonFunctions)? init(_ value: UIView & commonFunctions) { self.value = value } } // 字典声明 var elementsStore: [String: WeakCommonViewWrapper]
使用逻辑和你之前的泛型包装完全一致,通过wrapper.value就能拿到原实例,没有额外适配成本。
方案2:通用泛型包装改造
如果你需要同一个弱引用包装类适配多种类+协议组合类型,可以把内部弱引用的存储层改为AnyObject,对外通过泛型做类型转换,绕开编译器的泛型约束校验限制:
class WeakDictionaryData<T> { private weak var rawValue: AnyObject? var value: T? { get { rawValue as? T } set { rawValue = newValue as AnyObject? } } init(_ value: T) { // 注意:仅可传入类类型实例,传入结构体/枚举会触发运行时错误 // 你的场景下存储的都是UIView子类,属于类类型,无安全问题 self.rawValue = value as AnyObject } } // 声明组合类型包装时不会再报错 var var2: WeakDictionaryData<UIView & commonFunctions>
这个实现可以支持任意纯类类型、类+协议组合类型的弱引用存储,只要你确保传入的泛型参数T是类类型,就不会出现问题。
内容的提问来源于stack exchange,提问作者Alfredo Meraz
相关产品推荐
相关产品推荐

