본문 바로가기
🌱

Closure 2/3

by 방우 2022. 10. 29.
  • Closure?
  • vs. Function
  • Closure Expression
  • Capture
  • Escaping / Non-Escaping Closure
  • AutoClosure
  • swift 5.7

Capture

클로저가 매개변수나 지역변수가 아닌 주변 외부의 context를 사용하기 위해

주변 외부의 context를 참조하는 것 (Capturing by reference)

클래스 내부에서 클로저를 쓸 때 self를 써야함

 

 

🤔 왜?

 

 

그럼 클로저에서 클래스의 프로퍼티를 불러줄 때

 

클로저는 “애는 어디에서 온 아이야?”라고 묻는 것과 같음

 

자신을 담고있는 클래스일 수도 있고, 이름이 같은 매개변수일수도있고, 다른 클래스에서 데려온 프로퍼티일 수도 있으니까

명시적으로 클래스 내부에 self를 붙여 “음~ 얘는 니가 있는 클래스의 프로퍼티란다~”라고 말해주는것

 

컴파일러가 너 명시적으로 self붙여야한다~라고 말해주고있음

self를 일일이 쓰지 않아도 캡쳐리스트에 원하는 프로퍼티의 직접값을 캡쳐해서 캡쳐리스트에 담아놓으면 해당값을 쓸 수 있다.

 

캡쳐리스트에 명시한 요소가 참조타입이 아니라면 해당 요소들은 클로저가 생성될 때 초기화된다.

캡쳐는 사진을 찍는다고 보면 좋은데

클로저가 생성될 때 직전 캡쳐대상의 값을 캡쳐한다.

 

struct사진의 복사본을 갖고있는것

class사진의 캡쳐 직전의 url의 상태를 갖고있는 것

 

위의 예시에서 사진의 복사본인격인 struct의 요소 a는 초기값인 0이 캡쳐됐고, 변하지 않는 Immutable상태이다.

반면 class는 변수로 선언돼있어 캡쳐를 해도 변할 수 있는 것이다.

 

" 그럼 캡쳐할 프로퍼티가 30개면? 다 캡쳐리스트에 넣어야하나? "

 

이때 [self]가 등좡 👋

 

 

문제는 순환참조가 발생할 수 있다는 점 😇

아래를 보면 vc2가 action이 선언되면서 action을 물고, action에서 self를 캡쳐함으로써 action이 self를 마주보게 된다

➜ 순환참조

순환참조가 발생되어 콘솔창에 아무것도 찍히지 않았고, 메모리에 씬에 대한 참조값은 쌓이고 있는 상황

약한 참조를 통해 해결될 수 있고, 이 약한 참조를 캡쳐한 self의 프로퍼티에 접근할 수 있다.


 

함수 외부에서 반환값을 꼭 구현하지 않고 함수 실행값을 빼내서 이용하고 싶지 않나?

 

 

Escaping / Non - Escaping Closure

저장했다가 특정시점에 실행할 있다

외부의 변수에 값을 넣을 함수가 종료된 이후 호출 가능한 것이 탈출클로저

delay에 있는 closure는 매개변수로 전달된 클로저로써 delay 함수 내부 스코프 안에서 실행되고 종료돼야함

근데 DispatchQuecue로 보내 비동기로 실행되도록 하고 싶은 것

 

 

위의 함수는

delay함수 스코프를 벗어나게

 

그래서 컴파일러가 알려주는 것

 

“너 delay함수 흐름하고 상관없이 실행되네?

그럼 다른 함수에서 어떻게 실행돼서 끝날건데?

delay에서 실행되는게 아닌데 탈출클로저가 아니다? 뭐야!?”

ex) 비동기 처리, 외부 함수의 매개변수에 클로저를 넣어줄 때

 

그렇다면 귀찮으니까...

@escaping 걸어버리자!라는 생각에 도달할 수 있다.

 


 

컴파일러의 최적화

접근제어를 걸어주는 것처럼 컴파일러의 일을 줄여줌

우리가 접근제어자를 걸어서 컴파일러의 일을 줄였던것처럼

non-escaping 클로저는 컴파일러가 클로저의 scope주기를 알기때문에

때에 따라 클로저에서 사용하는 특정 객체에 대한 retain, release 등의 처리를 생략해

클로저 내 객체(변수등)의 라이프싸이클(life-cycle)을 효율적으로 관리할 수 있다

하지만 탈출클로저는 주기가 클로저를 포함한 외부함수에서 벗어나 실질적으로 클로저가 사용될 때가지 메모리 추적에 들어감


자동클로저

{ } 👉 ( )

함수의 인자로 전달되는 코드를 감싸서 자동으로 클로저로 만들어준다.

중괄호를 생략할 수 있음

이때 사용되는 클로저는 매개변수가 없고 리턴값만 존재해야함

  • @autoclosure는 기본적으로 non-escaping 클로저로써 만약 여기에 사용되는 클로저가 escaping 클로저라면 @escaping을 함께 붙여줘야한다.
  • 자동클로저를 사용하면 클로저를 호출할 때까지 내부코드가 실행되지 않는다.
  • 오토클로저를 걸어주면 클로저의 반환타입으로 매개변수의 타입이 바뀐다.
  • 이는 코드가 실행되는 시기를 제어할 수 있어 부작용이 있거나 계산비용이 많이 드는 코드에 유용하다.


swift 5.7

타입추론

기존에는 직접 클로저 반환 타입 또는 변수 타입을 명시해주어야 했다

5.7은 자동으로 타입을 추론해준다

'🌱' 카테고리의 다른 글

새싹프로그램 2기를 마무리하며  (0) 2022.12.11
Closure 3/3 - 고차함수  (1) 2022.10.29
Closure 1/3  (0) 2022.10.28
값전달 - 클로저 트러블 슈팅  (0) 2022.08.19
Equatable  (0) 2022.08.18