🍁
Swiftのweakについてメモ
メモリリークする可能性があるパターン
class Hoge {
var method: (() -> Void)?
init() {
print("Hoge init")
}
deinit {
print("Hoge deinit")
}
func call() {
method?()
}
}
class Meu {
let value: Int = 123
init(hoge: Hoge) {
print("Meu init")
hoge.method = {
print(self.value)
}
}
deinit {
print("Meu deinit")
}
}
var hoge: Hoge! = Hoge()
var meu: Meu! = Meu(hoge: hoge)
meu = nil // => Meu deinitが出力されない
hoge.call() // => クロージャーの参照が残り、実行される
hoge = nil // => hogeのdeinitと共にクロージャーの参照がなくなり、Meu deinitが出力される
console
Hoge init
Meu init
123
Hoge deinit
Meu deinit
メモリリークしないパターン
class Hoge {
// 中略
}
class Meu {
let value: Int = 123
init(hoge: Hoge) {
print("Meu init")
// weak selfなりunowned selfなりをつける
hoge.method = { [weak self] in
if let self = self {
print(self.value)
}
}
}
deinit {
print("Meu deinit")
}
}
var hoge: Hoge! = Hoge()
var meu: Meu! = Meu(hoge: hoge)
meu = nil // => この時点でMeu deinitが出力される
hoge.call() // => クロージャーの参照がなくなり実行されない
hoge = nil
console
Hoge init
Meu init
Meu deinit
Hoge deinit
結論
クロージャーの中でself
とかそのクラスの変数/関数を使う時は、weak/unowned self
をつける。
Discussion