본문 바로가기
Languages/Swift

You don’t (always) need [weak self] (해석)

by 탄이. 2020. 6. 17.

You don't (always) need [weak self] - Flawless iOS - Medium

 

You don’t (always) need [weak self]

We will talk about weak self inside of Swift closures to avoid retain cycles & explore cases where it may not be necessary to capture self weakly.

medium.com

In closure

let changeColorToRed = DispatchWorkItem { [weak self] in
  self?.view.backgroundColor = .red
}
  • 이 클로저에서 self가 어떻게 약하게 캡쳐되었는지 주목하십시오. 결국 self는 이 클로저의 바디에서 옵셔널로 바뀌 었습니다.
  • 우리는 정말로 [weak self]가 필요합니까? 사용하지 않으면 메모리 누수가 발생합니까?
  • 그것이 밝혀진 대답은 "때에 따라 다르다"는 것이지만, 먼저 몇 가지 역사를 이야기하겠습니다.

Unowned, Weak, and the 'Strong-Weak Dance'

  • 클로저는 정의 된 컨텍스트에서 상수 또는 변수를 강력하게 캡처하거나 닫을 수 있습니다.

  • 예를 들어, closure 내부에서 self를 사용하면 클로저 범위는 범위 수명 기간 동안 self에 대한 강력한 참조를 유지합니다.

  • self가 이 클로저에 대한 참조를 유지하는 경우 (나중에 어떤 시점에서 호출하기 위해), 당신은 강한 참조주기를 갖게 될 것입니다.

  • 다행히도 이 순환 참조를 피하기 위해 unowned 와 weak 같은 키워드(아래에서 설명하는 다른 도구와 마찬가지로)가 있습니다.

  • 내가 처음 스위프트를 배웠을 때 나는 모든 closure에서 [unowned self]를 사용했다.

  • 나중에 (여러번 충돌이 일어난 후), 이것은 풀어 버린 후에도 자기 자신을 풀어 내고 그 내용에 접근하려고하는 것과 같습니다. 즉, 매우 안전하지 않습니다!

  • [weak self]는 훨씬 더 안전한 방법으로 동일한 작업 (참조주기 방지)을 수행하지만, 프로세스 자체에서는 optional으로 변합니다.

  • 이 optional을 처리하기 위해 호출에 self?. 을 접두사로 붙일 수 있습니다. optional chaining.

  • 그러나보다 일반적인 접근법은 guard let 구문을 사용하여 클로저의 시작 부분에서 self에 대한 임시적인 강력한 참조를 만드는 것입니다.

  • Swift 언어의 초기 반복에서는 Strong-Weak 댄스라고 알려진 것을 수행하는 것이 일반적이었습니다.

  • 이 댄스에서는 다음과 같이 임시 non-optional strongSelf 상수에 self을 할당합니다.

  • 그런 다음 나중에 사람들은 코드를 단순화하기 위해 역습이있는 컴파일러 버그를 사용 (또는 악용)하기 시작했습니다.

  • 결국 Swift 4.2에서 언어는 guard가 self = self 구문을 허용하도록 공식 지원을 추가 했으므로 이것이 가능해졌습니다.

...........아 너무 길다 중략..........

결론

  • [unowned self] 는 거의 항상 나쁜 생각입니다.
  • 지연되지 않은 할당 해제에 신경 쓰지 않는 한 Non-escaping closure는 [weak self]를 필요로 하지 않습니다.
  • Escaping closure는 어딘가에 저장되거나 다른 closure로 전달되고 그 안의 객체가 closure에 대한 참조를 유지하면 [weak self]가 필요합니다.
  • guard let self = self 는 일부 경우 지연 할당 해제로 이어질 수 있으며 이는 의도에 따라 좋거나 나쁠 수 있습니다.
  • GCD 및 애니메이션 호출은 일반적으로 나중에 사용하기 위해 속성에 저장하지 않는 한 [weak self]가 필요하지 않습니다.
  • timer에 주의하십시오!
  • 확실하지 않은 경우, deinit 및 Instruments와 가깝게 지내십시오.

아래의 순서도가 [weak self]를 언제 사용하는지에 대한 유용한 요점을 제공한다고 생각합니다.

그림 설명

  • escaping closure입니까?
  • Do you mind if the closure delays deallocation of the objects referenced in it?
    • closure가 참조 된 객체의 할당 해제를 지연시키는 지 궁금합니까?
  • Is it stored in a property?
    • 그것은 속성에 저장되어 있습니까?
  • Is it passed to another closure?
    • 다른 closure로 전달 되었습니까?
  • Does any object inside the closure have a strong reference to the closure, or to another closure it was passed to?
    • 클로저 안의 어떤 오브젝트가 클로저에 대한 강력한 참조 또는 다른 클로저에 전달 된 오브젝트에 대한 강력한 참조를 가지고 있습니까?

댓글