我从
中汲取了一些灵感https://marcosantadev.com/swift-arrays-holding-elements-weak-references/
并且我希望能够维护一个数组,该数组持有对其元素的弱引用,以防万一这些元素在我的代码库中的其他位置释放,我不会将它们保留在我的数组中。
我希望实现尽可能安全,但是应该可以重用。
我使用的策略是这样声明弱引用容器。
class WeakRefContainer<T> where T: AnyObject {
private(set) weak var value: T?
init(value: T?) {
self.value = value
}
}
然后我要维护这些WeakRefContainers的数组,因此我创建了一个数组扩展名:
extension Array where Element: WeakRefContainer<AnyObject> {
func compact() -> [WeakRefContainer<AnyObject>] {
return filter { $0.value != nil }
}
}
调用紧凑方法时,我现在可以清理数组,以防需要清理东西。
我现在遇到一些编译问题,难以理解。 假设我有一个示例类
class SampleClass {
}
我尝试使用以下所有内容:
var weakReferencesArray = [WeakRefContainer<SampleClass>]()
let obj1 = WeakRefContainer.init(value: SampleClass())
let obj2 = WeakRefContainer.init(value: SampleClass())
weakReferencesArray.append(obj1)
weakReferencesArray.append(obj2)
weakReferencesArray.compact()
当我尝试调用紧凑型计算机时,出现以下错误消息:
MyPlayground.playground:29:21: 'WeakRefContainer<SampleClass>' is not a subtype of 'WeakRefContainer<AnyObject>'
有人可以解除对我的封锁吗?谢谢
答案 0 :(得分:1)
您的代码不起作用,因为WeakRefContainer<SampleClass>
不是WeakRefContainer<AnyObject>
的子类,因为在Swift中泛型是不变的。因此weakReferencesArray
不能使用从扩展名中添加的compact
方法。
通过协议可以解决此问题:
protocol WeakHolder {
var hasRef: Bool { get }
}
extension WeakRefContainer: WeakHolder {
var hasRef: Bool { return value != nil }
}
extension Array where Element: WeakHolder {
func compacted() -> [Element] {
return filter { $0.hasRef }
}
mutating func compact() {
self = compacted()
}
}
为了更好的Swift语义,我还将compact
重命名为compacted
,并用一个可变版本代替了原来的compact
。
答案 1 :(得分:1)
您可能希望扩展名适用于所有[WeakRefContainer<T>]
,其中T
可以是扩展AnyObject
的任何类型。
extension Array where Element: WeakRefContainer<T> {
但是,当前无法进行参数化扩展。参见this proposal。
您可以通过使compact
通用来解决此问题:
extension Array{
func compact<T>() -> [Element] where Element == WeakRefContainer<T> {
return filter { $0.value != nil }
}
}