보통 코드를 짤 때면 weak self를 써서 약한 참조를 걸어 메모리릭을 풀어 준다.

let changeColorToRed = DispatchWorkItem { [weak self] in
  self?.view.backgroundColor = .red
}

weak self가 정말 필요하냐는 질문에는 상황에 따라 다르다는 것을 알아야 할 것 같다.

순환참조를 피하기 위해 unowned self, weak self를 써야 할 때가 오는데 이는 상황에 맞게 잘 써야 한다.

unowned self는 강제로 self를 언래핑하고, 할당이 끝나도 접근을 해서 매우 위험하다.

그래서 결국 weak self를 쓰고, self의 옵셔널을 빼기 위해 guard 구문을 쓰는 것이다.

let changeColorToRed = DispatchWorkItem { [weak self] in
    guard let strongSelf = self else { return }
    strongSelf.view.backgroundColor = .red
}

예전에는 이렇게 작성해야했고

let changeColorToRed = DispatchWorkItem { [weak self] in
    guard let `self` = self else { return } // note the back ticks around self
    self.view.backgroundColor = .red
}

버그를 피하기 위해 이렇게 쓰다가

let changeColorToRed = DispatchWorkItem { [weak self] in
    guard let self = self else { return }
    self.view.backgroundColor = .red
}

swift4.2부터 이렇게 쓸 수 있게 된 것이다.

이 글에서의 핵심은 weak self를 많이 쓰는 시대지만, 꼭 안써도 될 때를 알아보자인 것 같다.

클로저에는 두 종류가 있는데 non-escape와 escape가 있따.

escaping clouser는 weak나 unowned를 쓰지 않았을 때 레퍼런스 사이클을 띄울 수 있다. 그런데 이것은

  1. 클로저가 프로퍼티를 저장하거나 다른 클로저에 패스할 경우
  2. 클로저 안의 오브젝트가(self같은 녀석) 클로저에 강한 참조를 유지하는 경우(전달받았던 다른 클로저)