技術書を読んでもずっと理解不能だったweakの使い方について、色々質問しまくって、ちょっとゴールが見えてきたので、いったんメモしておく
すべてからの参照を消さないとメモリが解放されない
classは参照型なので、例えば、
var hoge = aa(name:"unko")
ってものがあった場合でも、hoge = nilを入れたとしても、他からhogeへの参照がある場合、メモリは解放されないらしいです。
よく値型で物事を考えてしまうので、このあたりピンときづらいです。
例
class Person {
var name: String
var pet: Pet?
init(name: String) {
self.name = name
}
deinit {
}
}
class Pet {
var name: String
var owner: Person?
init(name: String) {
self.name = name
}
deinit {
}
}
上記の定義があったとして。
Person側から、Petへの参照があり、Petからもownerという変数でPersonへの参照が発生しそうです。
で、以下のようなコードがあるとする
var takamori: Person? = Person(name: "takamori")
var pochi: Pet? = Pet(name: "pochi")
takamori?.pet = pochi
pochi?.owner = takamori
/* で、takamoriを削除したくなり、nilをぶちこむ */
takamori = nil
この場合、一見takamoriはなくなったかのように見えた。
しかし、pochi?.ownerが参照しているので、var takamoriを参照するとnilかもしれないが、
pochi?.ownerからは、takamoriが見えている結果になっている。
参照型にnilを入れることは、メモリへの参照を消しただけであり、メモリ上にデータは残ってる。
このデータは、参照すべてがなくなった時に解放される以上、
pochi?.ownerが参照してる限り、データが残る。
こういうことを繰り返していくうちに、ずっとメモリの占有が増えていき、
メモリリークが起きる。
主軸ではないclassからの参照はweakをつける
そんな時にweakを使うらしい。
例えば、今回の場合、主軸となるclassがPersonだった場合。
つまり、Personのインスタンスが削除された場合、
そのインスタンスに参照してるやつも一緒に消したいとした場合にweakをつける。
よって、Personのインスタンスを削除した場合、データ丸ごとを消したいとすると、
Pet classからのPersonへの参照にweakをつける
class Person {
var name: String
var pet: Pet?
init(name: String) {
self.name = name
}
deinit {
}
}
class Pet {
var name: String
weak var owner: Person?
/* person側が破棄されたら、こちらも自動的に履きされる*/
init(name: String) {
self.name = name
}
deinit {
}
}