的问题是,weakDelegates
是很强的参考和它的参考类型WeakDelegateContainer的其元素是很强的参考。
您的情况是为什么类NSHashTable存在。使用weakObjects()
进行初始化。这会给你一套ARC-weak引用,当引用的对象不存在时(不需要任何额外的簿记,也不需要你的WeakDelegateContainer类型),每个引用都会被删除和删除。
贵定将不得不分型为控股AnyObject,但你可以很容易地调解,以确保您提供和获取SomeDelegate符合的对象:
let list = NSHashTable<AnyObject>.weakObjects()
func addToList(_ obj:SomeDelegate) {
list.add(obj)
}
func retrieveFromList(_ obj:SomeDelegate) -> SomeDelegate? {
if let result = list.member(obj) as? SomeDelegate {
return result
}
return nil
}
func retrieveAllFromList() -> [SomeDelegate] {
return list.allObjects as! [SomeDelegate]
}
功能retrieveAllFromList()
仅列出仍然存在的对象。任何已经存在的对象已在NSHashTable中更改为nil
,并且不包含在allObjects
中。这就是我所说的“没有额外的簿记”; NSHashTable已经完成了簿记。
这里是代码,测试它:
func test() {
let c = SomeClass() // adopter of SomeDelegate
self.addToList(c)
if let cc = self.retrieveFromList(c) {
cc.someFunction()
}
print(self.retrieveAllFromList()) // one SomeClass object
delay(1) {
print(self.retrieveAllFromList()) // empty
}
}
或者,你可以使用NSPointerArray。它的要素指针到无效的,它可以是一个有点冗长斯威夫特使用,但你只需要编写访问函数一次(信贷https://stackoverflow.com/a/33310021/341994):
let parr = NSPointerArray.weakObjects()
func addToArray(_ obj:SomeDelegate) {
let ptr = Unmanaged<AnyObject>.passUnretained(obj).toOpaque()
self.parr.addPointer(ptr)
}
func fetchFromArray(at ix:Int) -> SomeDelegate? {
if let ptr = self.parr.pointer(at:ix) {
let obj = Unmanaged<AnyObject>.fromOpaque(ptr).takeUnretainedValue()
if let del = obj as? SomeDelegate {
return del
}
}
return nil
}
这里是代码进行测试:
let c = SomeClass()
self.addToArray(c)
for ix in 0..<self.parr.count {
if let del = self.fetchFromArray(at:ix) {
del.someFunction() // called
}
}
delay(1) {
print(self.parr.count) // 1
for ix in 0..<self.parr.count {
if let del = self.fetchFromArray(at:ix) {
del.someFunction() // not called
}
}
}
有趣的是,我们的SomeClass的熄灭的存在后,我们的磁盘阵列的count
保持在1 - 而是通过自行车来调用someFunction
,还有就是someFunction
没有呼叫。这是因为数组中的SomeClass指针已被替换为nil
。与NSHashTable不同,该阵列不会自动清除其nil
元素。他们这样做没有坏处,因为我们的访问代码防范的错误,但如果你想压缩数组,这里是做它一招(https://stackoverflow.com/a/40274426/341994):
self.parr.addPointer(nil)
self.parr.compact()
的那个问题,是指符合类答案到AnyObject。我有一个不符合AnyObject的协议对象数组。 – Leontien
协议无法符合自己的要求,因此当使用协议本身作为你想要容纳的弱包装对象时,链接的答案不能直接用于bat(我们可能会想'用'SomeDelegate'替换'AnyObject'约束)链接到。但是,您可以查看[以下问答](http://stackoverflow.com/questions/32807948/using-as-a-concrete-type-conforming-to-protocol-anyobject-is-not-supported),实现一个自定义容器,允许通过弱引用来保存'class'约束协议实例。 – dfri
dfri的链接帮助。我使用了Kyle Redfearn的答案,因为我不需要一个通用的解决方案。我会把我的解决方案放在这个问题的答案中,所以它会更容易找到其他人。 – Leontien