Ios NSMapTable中的迭代键将永远保留弱值
我试图使用Ios NSMapTable中的迭代键将永远保留弱值,ios,swift,Ios,Swift,我试图使用NSMapTable来弱存储一些对象实例,这些实例由字符串索引 (我的用例是存储一些有关远程服务器的缓存元数据,并让每个活动客户端共享该元数据。当不再有客户端连接到该特定服务器时,应将元数据从内存中删除。) 这一切都很好,只要我从未迭代过键。看起来,如果我迭代了一个特定的键,该键的值将永远不会被释放 我已设法将其简化为一个小代码段,以显示问题: import Foundation class Foobar { let id: String init(_ id: Str
NSMapTable
来弱存储一些对象实例,这些实例由字符串索引
(我的用例是存储一些有关远程服务器的缓存元数据,并让每个活动客户端共享该元数据。当不再有客户端连接到该特定服务器时,应将元数据从内存中删除。)
这一切都很好,只要我从未迭代过键。看起来,如果我迭代了一个特定的键,该键的值将永远不会被释放
我已设法将其简化为一个小代码段,以显示问题:
import Foundation
class Foobar {
let id: String
init(_ id: String) { print("init \(id)"); self.id = id }
deinit { print("deinit \(id)") }
}
let map = NSMapTable<NSString, Foobar>(keyOptions: .strongMemory, valueOptions: .weakMemory)
func addSome() {
let a = Foobar("a")
let b = Foobar("b")
let c = Foobar("c")
map.setObject(a, forKey: "a")
map.setObject(b, forKey: "b")
map.setObject(c, forKey: "c")
let e = map.keyEnumerator()
print("nextObject: \(e.nextObject() ?? "nil")")
print("nextObject: \(e.nextObject() ?? "nil")")
print("nextObject: \(e.nextObject() ?? "nil")")
print("nextObject: \(e.nextObject() ?? "nil")")
}
addSome()
print(map.object(forKey: "a") ?? "nil")
print(map.object(forKey: "b") ?? "nil")
print(map.object(forKey: "c") ?? "nil")
<代码>导入基础
福巴级{
let id:String
init(id:String){print(“init\(id)”;self.id=id}
deinit{print(“deinit\(id)”)}
}
let map=NSMapTable(键选项:.strong内存,值选项:.weakMemory)
func addSome(){
设a=Foobar(“a”)
设b=Foobar(“b”)
设c=Foobar(“c”)
map.setObject(a,forKey:“a”)
map.setObject(b,forKey:“b”)
map.setObject(c,forKey:“c”)
设e=map.keyEnumerator()
打印(“nextObject:\(e.nextObject()??“nil”))
打印(“nextObject:\(e.nextObject()??“nil”))
打印(“nextObject:\(e.nextObject()??“nil”))
打印(“nextObject:\(e.nextObject()??“nil”))
}
addSome()
打印(映射对象(forKey:“a”)??“nil”)
打印(映射对象(forKey:“b”)??“nil”)
打印(映射对象(forKey:“c”)??“nil”)
如果我注释掉一个或多个e.nextObject()
调用,相应键的值将被正确释放,map.object(forKey:)
将正确返回nil
在我以某种方式使用完枚举器之后,是否必须手动清理它?显然,映射枚举器返回“autorelease”对象–这些对象在当前autorelease池的作用域离开时释放 在iOS或macOS应用程序中,当程序控制返回到主事件循环时会自动发生。在任何情况下,您都可以使用本地 在枚举后立即释放对象 备注:
nsemulator
是一个序列
,因此您可以使用for循环枚举它:
autoreleasepool {
let e = map.keyEnumerator()
for case let key as String in e {
print(key)
}
}
autoreleasepool {
let e = map.keyEnumerator()
for case let key as String in e {
print(key)
}
}