[iOS] Closure Capture List

RudinP·2024년 4월 2일
0

Study

목록 보기
217/226

Closure Capture

  • 클로저에서 self에 접근하는 것은 클로저의 실행이 끝나기까지 self를 소유하게 된다.
  • 즉, self의 참조 카운트를 1 증가시킨다.
  • 클로저의 실행이 끝날 때까지 self도 메모리에서 사라지지 않는다는 것이다.
    • 여기서는 ViewController
  • 이 클로저는 뷰가 사라진 후, 5초 뒤에 실행되고 사라지기 때문에 그 때 vc의 참조 카운트가 0이 되고 deinit

지연 속성 lazy

  • 모든 속성은 인스턴스 초기화가 완료되기 전까지 접근 불가능
  • 이걸 실행하기 위해서는 value에 접근하는 시점을 초기화 뒤로 미뤄야함.
  • lazy 키워드를 사용하면 지연 저장 속성이 된다.
    • 인스턴스가 초기화 될 때 초기화되지 않고, 인스턴스에 처음 접근할 때 초기화가 됨

Closure에서 강한 참조 사이클

클로저 또한 강한 참조 사이클을 발생시킬 수 있다.

  • weak 혹은 unowned를 사용하면 되엇으나, 클로저가 저장된 속성에는 weak를 적용할 수 없다.
  • 이를 해결하기 위해서는 closure capture list를 사용한다.

Closure Capture List

{ [list] (parameters) -> ReturnType in
	statements
}

{ [list] in
	statements
}
//클로저 캡처 리스트를 사용한다면, 이를 클로저 바디와 구분해야 하기 때문에 in을 생략해서는 안된다.

값형식 캡처


원래대로라면 클로저에서 캡처한 경우 원본을 캡처한다.

그러나, 값 형식을 클로저 캡처 리스트에 추가하면 원본 대신에 복사본을 캡처한다.

참조형식 캡처

{ [weak instanceName, unowned instanceName] in
	statements
}

  • 다만 이렇게만 할 시, 강한 참조 사이클 발생

weak

unowned

여기서는 weak, unowned 어느것을 사용해도 상관 없다.
왜냐하면 클로저의 생명주기 때문이다.

  • 클로저는 viewDidLoad()가 호출되는 시점에서 만들어짐
  • 클로저가 여기서는 속성이기 때문에 인스턴스가 사라지는 시점에 같이 사라짐
  • 클로저 안에서는 인스턴스에 언제든지 접근 가능.(인스턴스가 먼저 사라지지 않으니까)
    클로저 안에서 접근하는 대상의 생명주기가 클로저와 같거나 더 길다면 weak, unowned 어느 것을 사용해도 상관 없다.

결론

보통 클로저를 사용할 때는 강한 참조가 발생하는지 바로 확인하기 힘드므로, 왠만하면 클로저 사용 시 클로저 캡처 리스트를 사용하는 것이 옳다.
또한 weak을 사용할지, unowned를 사용할지 에서 대상과 클로저의 생명주기의 길이를 꼭 비교하고 선택하자. (클로저의 생명주기 > 대상의 생명주기 일 경우 nil이나 crash)

profile
곰을 좋아합니다. <a href = "https://github.com/RudinP">github</a>

0개의 댓글