arrays - 在 Swift 中从字典中获取值或键时保留循环

标签 arrays dictionary swift retain-cycle

当我从字典中获取值并将它们放入数组时,我无法再释放内存。我试图从 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.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 时,我正在玩这个问题:

    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。

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

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

for _ in myDictionary { }

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

因此,您的示例中的数组是一条红鲱鱼,我认为您发现了字典访问的错误。

关于arrays - 在 Swift 中从字典中获取值或键时保留循环,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24700178/

相关文章:

c++ - 下界上界给出相同的结果

java.lang.ArrayIndexOutOfBoundsException : 0 (stack implementation) 异常

C++ std::map 和 std::pair<int, int> 作为键

python - 已排序的字典列表

swift - 如何在一天中的不同时间创建通知?

ios - 将 View Controller 关闭到特定的 View Controller

Swift - 编码和解码字典 [String :Any] into plist

javascript - 比较 Canvas 上两个位置的 x/y

python - 我该如何优化这段代码?以及一般如何优化 Python for 循环?

Java HashMap.get(key) 和 TreeMap.get(key) equals 和compareTo 方法的用法