【发布时间】:2014-07-11 14:31:54
【问题描述】:
当我从字典中获取值并将它们放入数组时,我无法再释放内存。我试图从 Array 和 Dictionary 中删除所有对象,但这些对象仍然存在于某处(未调用 deinit)。
我是这样玩的:
class MyData {
let i = 0
init () {
NSLog("Init")
}
deinit {
NSLog("Deinit")
}
}
var myDictionary:Dictionary<String, MyData> = ["key1":MyData(), "key2":MyData()]
// Init was called twice
// here is the problem: extract values from Dictionary
var myValues = Array(myDictionary.values)
myValues = [] // nothing - ok, strong references are still in the dictionary
myDictionary = [:]
// Why Deinit was not called???
如果我删除这两行进行值提取,则正常调用 Deinit
var anotherDictionary:Dictionary<String, MyData> = ["key1":MyData(), "key2":MyData()]
anotherDictionary = [:]
// Deinit is called twice
var myArray:MyData[] = [MyData(), MyData()]
myArray = []
// Deinit is called twice
我在这里做错了什么?
当不再需要对象时,应如何以适当的方式删除对象以释放内存?仅当从 Dictionary(Dictionary.values 或 Dictionary.keys)中提取键或值时才会出现此问题。
编辑:
我为这种情况做了一个解决方法。如果我使用 NSDictionary 而不是 Dictionary 并首先提取键,然后在 for 循环中取值,那么它就可以工作。
var myDictionary:NSDictionary = ["key1":MyData(), "key2":MyData()]
// called Init twice
var myKeys:String[] = myDictionary.allKeys as String[]
var myValues:MyData[] = []
for key in myKeys {
myValues.append(myDictionary[key] as MyData)
}
myKeys = []
myDictionary = [:]
myValues = []
// Deinit is now called twice, but I'm not sure about keys...
但是,如果我使用 allValues 而不是 allKeys,那么它将不再起作用。
...
var anotherValues = myDictionary.allValues
anotherValues = []
myDictionary = [:]
// deinit is not called again - very scary...
【问题讨论】:
-
有趣的实验。我想知道是否每次克隆集合时都会发生这种情况,或者它是否特定于字典键。我的猜测是前者。
-
我认为这是一个缺陷。即使你把它放在一个自动释放池中,它也不会调用 deinit。
-
这是在游乐场吗?
-
@Matt - 不,它在一个包含在一个函数中的项目中。我也在操场上进行了测试,但即使在正常情况下(最后两行代码)也不会调用 deinit。
-
很好;作为调试显示的一部分,playgrounds 倾向于挂在引用上,所以我只是确保这不会混淆问题。
标签: arrays dictionary swift retain-cycle