[Effective Objective-C] #40 블록이 자신을 소유한 객체를 다시 소유함으로써 발생하는 리테인 순환을 조심하라
출처 : Effective Objective-C
-
블록을 주의 깊게 사용하지 않으면 리테인 순환이 쉽게 발생한다.
-
완료 핸들러 블록은 리테인 순환이 발생할 수 있는 참조를 nil 로 만들어 주어야 한다.
-
이 리테인 순환 문제는 완료 콜백 블록을 사용하는 API 에서 흔히 발생하는 것이다.
그렇기 때문에 꼭 알고 있어야 한다.
이 문제는 적절한 순간에 참조 중 하나를 제거함으로써 풀 수 있다.
그러나 항상 참조를 제거할 수 있는 순간이 온다고 보장할 수 없다.
예를 들어 리테인 순환은 오직 완료 핸들러가 동작할 때만 깨질 수 있다.
완료 핸들러가 실행되지 않으면 리테인 순환이 결코 깨지지 않는다.
그리고 누수가 발생할 것이다.
-
리테인 순환이 발생할 수 있는 또 다른 곳은 완료 핸들러 블록 방식을 사용하는 곳이다.
이 리테인 순환은 완료 핸들러 블록이 블록을 소유하는 객체를 참조할 때 발생한다.
-
완료 핸들러를 public 이라고 사용자에게 말하는 순간 캡슐화가 깨질 것이다.
이 경우 리테인 순환을 합리적으로 제거하는 유일한 방법은 사용자가 핸들러를 잡고 있는 프로퍼티를 스스로 해제하는 것이다.
하지만 이 또한 합리적이지 않다.
사용자가 이렇게 하리라고 가정할 수 없기 때문이다.
사용자들은 누수가 생기는 것에 대해 여러분을 비난할 것이다.
-
핵심은 블록이 잡을 수 있는 가능성이 있는 객체가 무엇인지 생각해 보는 것이다.
객체를 잡으면 리테인되기 때문이다.
이런 블록을 잡은 객체들 중에 직간접적으로 다시 블록에 의해 리테인된 객체가 있으면 반드시 이 리테인 순환을 깨뜨릴 방법과 깨뜨릴 시점을 생각해야 한다.
기억할 점
-
블록에 잡힌 객체가 직간접적으로 다시 그 블록을 리테인할 때 발생하는 리테인 순환을 조심하라.
-
특정 시점에서 반드시 리테인 순환이 깨질 것이라는 점을 보장하라.
여러분의 API 사용자에게 이 책임을 전가하면 안 된다.
'프로그래밍 놀이터 > iOS' 카테고리의 다른 글
[Effective Objective-C] #41 동기화에는 락보다는 디스패치 큐를 사용하라 (0) | 2017.10.06 |
---|---|
[Effective Objective-C] 목차와 요약을 통해 한 눈에 알아보는 Effective Objective-C #33 ~ #40 (0) | 2017.10.05 |
[Effective Objective-C] #39 핸들러 블록을 사용해 코드가 여러 개로 나뉘는 것을 막으라 (0) | 2017.10.03 |
[Effective Objective-C] #38 많이 사용하는 블록 타입은 typedef 를 이용해 타입을 생성하라 (0) | 2017.10.02 |
[Effective Objective-C] #37 블록을 이해하라 (0) | 2017.10.01 |
댓글