Closure

seocho·2022년 8월 19일
0

iOS

목록 보기
2/24
  • 사용자의 코드 안에서 전달되어 사용할 수 있는 로직을 가진 중괄호로 구분된 코드의 블럭이며, 일급 객체의 역할을 할 수 있다.
  • 참조 타입
  • 일종의 고차함수 인데, 내 생각엔 간단하게 간소화된 함수? 라고 생각한다.

그럼 일급 객체는?

일급 객체는 전달 인자로 보낼 수 있고, 변수/상수 등으로 저장하거나 전달할 수 있으며, 함수의 반환 값이 될 수도 있다.

값 캡쳐

매개변수나 지역변수 혹은 외부 context를 참조하는 것
=> 외부 context가 없어져도 사용할 수 있음 (Capturing by reference)

value type에 대한 capturing by reference

이 경우에도 reference count가 1 증가한다.

캡쳐리스트

참조한 변수들을 얼마나 강하게 캡쳐해야하는지를 명시하는 것

 { [] in ~ }

캡쳐 시점

var index = 0
var closureArr: [() -> ()] = []

for _ in 1...5 {
  closureArr.append({print(index)})
  index += 1
}

for i in 0..<closureArr.count {
    closureArr[i]()
}

=> 5 5 5 5 5

var index = 0
var closureArr: [() -> ()] = []

for _ in 1...5 {
  closureArr.append({[index] in 
   		print(index)       
   })
  index += 1
}

for i in 0..<closureArr.count {
    closureArr[i]()
}

=> 0 1 2 3 4

값타입 => 클로져가 생성될 때 캡쳐

참조타입 => 클로져가 호출될 때 캡쳐

메모리 누수

reference count가 초기화 되지 않고 화면 이동이 일어났을 때 메모리 누수 발생 (순환 참조 등)
=> 캡쳐 리스트로 해결 가능 (weak , unowned)

unowned는 nil이 들어오는 것을 처리할 수 없기 때문에 조심히 사용해야한다.

optional closure

closure를 optional로 지정하면 더이상 closure타입이 아닌 optional타입이 된다.

() -> () : closure
(() -> ())? : optional

결론적으로 optional closure를 사용하면 기존의 일반 파라미터 처럼 사용이 되면서 자동으로 escaping으로 변경되기 때문에 escaping키워드를 사용하지 않아도 된다.

escaping vs non-escaping

closure는 기본적으로 non-escaping
=> 함수가 종료되고 나서 클로저가 실행될 수 없다.

non-escaping

함수 내부에서 직접 실행하기 위해서만 사용 (함수가 종료되기 전에 무조건 실행 되어야 하는 경우)

escaping

파라미터로 받은 closure를 비동기로 사용하고 싶을 때 사용
=> 함수의 흐름에 상관 없이 실행되는 클로저

profile
iOS 개린이

0개의 댓글