9

当我从字典中获取值并将它们放入数组时,我无法再释放内存。我试图从数组和字典中删除所有对象,但这些对象仍然存在于某处(未调用 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...
4

1 回答 1

5

我不认为这是一个保留周期。我可以简单地通过迭代字典中的值来重现这一点,甚至不引入数组,也不对它们做任何事情。当我注释掉一些代码并发现这仍然没有调用 deinit 时,我正在处理这个问题:

    var myDictionary:Dictionary<String, MyData> = ["key1":MyData(), "key2":MyData()]
    for (_, item) in myDictionary {
        //myValues.append(item)
    }
    myDictionary = [:]
    // Why Deinit was not called???

如果您完全取出for循环,则按预期调用 deinit。如果你把它放回去——只是循环,不做任何事情——那么你就不会得到一个 deinit。

我会说这是某种字典访问中的错误;它不像数组和字典之间的引用循环那么复杂。

我可以用这个作为我的for循环来重现上面的内容:

for _ in myDictionary { }

...如果我把那条线去掉,那就没问题了。这是我能找到的最简单/最奇怪的情况。

因此,您示例中的 Array 是一个红鲱鱼,我认为您已经发现了字典访问的错误。

于 2014-07-21T16:37:46.733 回答