強参照と弱参照は意識して使い分けてる?と言われ、ドキッとした。
2回目言われると心臓が止まってしまうので理解が曖昧な今
深夜テンションで雑にまとめる!!!
weak selfがないと何が起こるのか
「循環参照してメモリリークする」です。 なんのこっちゃ?
そのまえにARCとは
swiftではARC(Auto Reference Counting)という仕組みを用いて、自動でメモリの管理を行なってくれています。そのお陰で、私でも脳死でコードを書くことが出来たんですね。
このARCはランタイム時に自動で参照をカウントする仕組みで、
例えば、
class Hoge {
init() {
print("init")
}
deinit {
print("deinit")
}
}
こういうクラスがあったとしましょう。
var ref1: Hoge? = Hoge()
var ref2: Hoge? = ref1
var ref3: Hoge? = ref1
この時、Hoge()は
- ref1
- ref2
- ref3
の3つから参照されています。(参照カウンター = 3)
Hogeが解放される時にdeinitが呼ばれます。
deinitを呼び出すにはどうすれば良いでしょうか。
キルするには参照している箇所をなくせば良いですね。
ref1にnilを入れてみてもdeinitは呼ばれていません。
ref1とref2にnilを入れてみてもdeinitは呼ばれていません。
ref1,ref2,ref3にnilを入れて初めて参照されている箇所がなくなり、Hogeをキルすることが出来ました。
これがざっくりとした参照カウントという概念
(説明が面倒なので、他のわかりやすい記事を見てね)
これはインターンのメンターさんに教えていただいた
class HogeViewController: UIViewController {
let hogeView: HogeView = .init()
var counter: Int = 0
// 強参照
hogeView.state = { _ in
self.counter += 1
}
}
class HogeView: UIView {
var state: (() -> Void)?
// ボタンが押された時、ここが呼ばれるとする
func button() {
state?()
}
}
hogeViewのbuttonが呼ばれた時、
hogeView.state = { _ in
self.counter += 1
}
が動く。
この時のselfはHomeViewControllerのことですな。
hogeView.state内のHomeViewControllerのcounterを強参照しています。(参照カウンターが増える)
この時、HomeViewControllerが解放されようとしますが、参照カウンター(HomeViewControllerが無くなると困るよ〜って言ってる箇所)が0にならずメモリ解放ができません。これによりメモリリーク(使ってないのにメモリが確保されている状態)に陥る。
weak selfを使うとどうなるのか
参照カウンターが増えません。
つまり、HomeViewControllerと運命を共にするさだめの、参照箇所は参照カウンターが増える必要はないですね。
class HogeViewController: UIViewController {
let hogeView: HogeView = .init()
var counter: Int = 0
// 弱参照
hogeView.state = { [weak self] in
self?.counter += 1
}
}
ここで、IBOutlet について、なぜweak selfがついているのか疑問に思いました。
@IBOutlet weak var myView: UIView!
UIKitを使ってるとこんなコードをよく見ますね
下記の記事を参考にしてください
https://qiita.com/chocovayashi/items/a96adc1356b7c45524b7
参考記事の結論がわかりやすかったので引用
IBOutletのViewをremoveする予定がなければ、適当でOK
IBOutletのViewをremoveし、その後は使わなければ、@IBOutlet weak var hogehoge: HogeView!
IBOutletのViewをremoveし、その後また使うなら@IBOutlet var hogehoge: HogeView!
なにも予想できない場合は、@IBOutlet weak var hogehoge: HogeView?
参考
https://zenn.dev/mhackit/articles/a0b1c6e780c3c6aabe45
https://qiita.com/reo0612/items/b0d1ee00ebf3a0e7c857