Slide 1

Slide 1 text

Swiftでなんで[weak self]するのか? 2018/03/30 oyuk(@oydku) 1

Slide 2

Slide 2 text

自己紹介 oyuk(@oydku) プログラマ 2

Slide 3

Slide 3 text

weak selfについて よくあるアレ { [weak self] event in guard let strongSelf = self else { return } // なんかする } 3

Slide 4

Slide 4 text

結論から [weak self] と書くことでクロージャが self を弱参照し、クロージャと self の循環参照を防ぐ 4

Slide 5

Slide 5 text

は? [weak self] ってなんじゃその書き方は 弱参照?循環参照? 5

Slide 6

Slide 6 text

[weak self] ってそんな書き方ありなん? 今回の本質じゃないから軽く 「 [weak self] と書くことでクロージャが self を弱参照する」これだけ覚えておいて ちなみに [weak self] はキャプチャリストと呼ぶ 6

Slide 7

Slide 7 text

弱参照?循環参照? 参照カウントというGCの概念 これを理解するために 参照カウントについて Swiftの参照カウント(Automatic Reference Counting)について少し 7

Slide 8

Slide 8 text

参照カウント GCの一種 オブジェクトに対して参照している他のオブジェクトの数を記憶する(参照カウント) 1以上なら生きている。メモリに割り当てられている 0になると死。解放される 8

Slide 9

Slide 9 text

参照カウント 例1 class Hoge {} // Hoge のインスタンスの参照カウントが1 になる var h: Hoge? = Hoge() 9

Slide 10

Slide 10 text

参照カウント 例2 class Hoge {} // Hoge のインスタンスの参照カウントが1 になる var h: Hoge? = Hoge() // Hoge のインスタンスの参照カウントが0 になり解放される h = nil 10

Slide 11

Slide 11 text

参照カウント 例3 class Hoge { var fuga: Fuga? } class Fuga { var hoge: Hoge? } var hoge: Hoge? = Hoge() // hoge の参照カウント1 var fuga: Fuga? = Fuga() // fuga の参照カウント1 hoge.fuga = fuga // hoge の参照カウント2 fuga.hoge = hoge // fuga の参照カウント2 hoge = nil // hoge の参照カウント1 fuga = nil // fuga の参照カウント1 hoge も fuga も参照することができないのにメモリ上に残ったままになっている hoge と fugga で循環参照が起きている 11

Slide 12

Slide 12 text

参照カウント 例4 class Hoge { private var closure: (() -> Void)? private var count = 0 init() { closure = createClosure() } func createClosure() -> (()-> Void) { return { self.count += 1 } } } var h: Hoge? = Hoge() // Hoge の参照カウント2 , closure の参照カウント1 h = nil // Hoge の参照カウント1 hoge と closure で循環参照が起きている 12

Slide 13

Slide 13 text

循環参照 var h: Hoge? = Hoge() // Hoge の参照カウント2 , closure の参照カウント1 h = nil // Hoge の参照カウント1 13

Slide 14

Slide 14 text

循環参照解決策 class Hoge { private var closure: (() -> Void)? private var count = 0 init() { closure = createClosure() } func createClosure() -> (()-> Void) { return { [weak self] in self?.count += 1 } } } var h: Hoge? = Hoge() // Hoge の参照カウント1 , closure の参照カウント1 h = nil // Hoge の参照カウント0 解放される! 14

Slide 15

Slide 15 text

なぜ func createClosure() -> (()-> Void) { return { [weak self] in self?.count += 1 } } [weak self] は self を参照するが参照カウントは+1しないという意味 これが弱参照 ちなみに今までのは強参照 循環参照が起こらなくなる 15

Slide 16

Slide 16 text

なぜ var h: Hoge? = Hoge() // Hoge の参照カウント1 , closure の参照カウント1 h = nil // Hoge の参照カウント0 16

Slide 17

Slide 17 text

なぜ hは参照カウントは0なので解放される closureも参照カウント0なので解放される 17

Slide 18

Slide 18 text

まとめ { [weak self] event in guard let strongSelf = self else { return } // なんかする } [weak self] と書くことでクロージャが self を弱参照し、クロージャと self の循環参照を 防ぐ 18

Slide 19

Slide 19 text

19