Ad Clicks : Ad Views : Ad Clicks : Ad Views : Ad Clicks : Ad Views : Ad Clicks : Ad Views : Ad Clicks : Ad Views : Ad Clicks : Ad Views : Ad Clicks : Ad Views : Ad Clicks : Ad Views : Ad Clicks : Ad Views : Ad Clicks : Ad Views : Ad Clicks : Ad Views : Ad Clicks : Ad Views : Ad Clicks : Ad Views : Ad Clicks : Ad Views : Ad Clicks : Ad Views : Ad Clicks : Ad Views : Ad Clicks : Ad Views :

[Swift] Closure Capture List

/
/
/
101 Views

간단한 인덱스가 1씩 증가하는 클로저를 배열로 만들어서 출력하는 간단한 예제이다.
위 예제를 실행하면 결과값을 어떻게 출력 될까?

5
5
5
5
5

0, 1, 2 ,3 ,4 라고 답을 생각하시는 분도 있을 것이다. 저 또한 출력된 결과값을 보고 당황스러웠었다.

Closure 는 Reference Type 인 것을 알면 어느정도 해당 결과값에 대한 것에 대해 인지가 될 것이다. 클로저의 매개변수로 값을 전달하는 것이 아닌 클로저 바깥의 값을 사용할 때에는 해당 값을 참조하여 사용하기 때문에 위의 결과값이 나온 것 이다.

즉, 클로저 내부에서 참조하는 index 의 최종 값은 5이기 때문에 5, 5, 5, 5, 5 가 찍히는 것 이다.

그리고 클로저 내부에서 사용하는 index는 강한 참조(strong) 하게 참조 된다는 것에 주의해야 한다. 클로저가 메모리에서 해제 되기 전까지는 index는 메모리에서 해제되지 않는다.

간단한 예제이지만 간혹 이런 실수로 예기치 않는 버그를 만들 수 있는 점에 주의해서 코딩해야한다.

문제 해결

클로저 외부의 index 를 바로 참조하지 않고, index 를 복사해서 그 값을 사용하면 위의 문제를 해결할 수 있다. 이것이 스위프트에서 제공하는 캡처 리스트다.

클로저 파라메터 선언 앞에 대괄호로 변수 이름을 입력하면 그 값을 캡처해서 클로저에서 사용한다는 의미이다.

index 변수명을 그대로 사용하지 않고, 다른 변수명으로 치환하는 것도 가능하다. 이렇게 치환해서 하는 것이 가독성도 좋고, 캡쳐리스트를 했다는 것도 바로 파악이 가능해서 추천한다.

위의 문제는 캡처 리스트를 사용하지 않고 for 루프를 위와 같이 수정하면 해결이 된다. for 문의 Range 를 사용하면 index 는 새로운 인스턴스가 매 순간 생성되기 때문에 캡처 리스트를 사용할 필요가 없어진다.

Leave a Comment

이메일은 공개되지 않습니다.

This div height required for enabling the sticky sidebar