ディクショナリから値を取得して配列に入れると、メモリを解放できなくなります。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???
値を抽出するためにこれら 2 行を削除すると、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) からキーまたは値が抽出された場合にのみ発生します。
編集:
この場合の回避策を作成しました。Dictionary の代わりに NSDictionary を使用し、最初にキーを抽出してから 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...
しかし、allKeys の代わりに allValues を使用すると、機能しなくなります。
...
var anotherValues = myDictionary.allValues
anotherValues = []
myDictionary = [:]
// deinit is not called again - very scary...