[TIL] 클로저 Closure

술술·2024년 3월 12일

TIL

목록 보기
6/21

mutating

  • mutating : struct나 enum과 같은 값타입에서 사용

💡 구조체(Structs)나 열거형(Enum) 내에서 메서드(Method)가 해당 구조체
또는 열거형의 속성을 수정할 수 있도록 한다.

  • struct나 enum 안에 있는 프로퍼티의 값을 변경할 때 사용
  • 구조체나 열거형의 인스턴스가 상수로 선언되면 해당 인스턴스의 속성을 변경할 수 없습니다.
  • 메서드 내에서 해당 인스턴스의 속성을 변경하려면 mutating 키워드를 사용하여 해당 메서드가 해당 인스턴스의 속성을 수정할 수 있도록 허용해야 합니다.

capture

📌 캡처(Capture)

흔히 들어온 캡처와는 느낌이 살짝 다를 수 있다. 캡처한다는 말을 들으면 스냅샷이 제일 먼저 떠오른다. 그 순간을 그대로 사진처럼 담아 값도 정의되는 순간 그대로 가져올 것만 같은데, 실제로 그렇지 않다.
여기서 말하는 캡처는, 해당 값이 사라지지 않도록 잡아둔다는 뜻이 강하다. 사진을 찍다의 capture가 아니라, 뭔가를 잡을 때의 capture에 가깝다.

func makeIncrementer(forIncrement amount: Int) -> () -> Int {
  var runningTotal = 0
  
  func incrementer() -> Int {
    runningTotal += amount
    return runningTotal
  }
  
  return incrementer
}
  • makeIncrementer 라는 함수는 () -> Int 타입을 반환하는 함수로, 클로저를 반환한다고 볼 수 있다. 읽어보면 incrementer 라는 함수를 반환하고 있는걸 확인할 수 있다.
  • 여기서 incrementer 안을 보면, incrementer 외부에 있는 runningTotal이라는 변수를 참조하고 있다. 그러면 incrementerrunningTotalamount를 캡처했다, 고 생각할 수 있을 것이다.
let incrementByTen = makeIncrementer(forIncrement: 10)
incrementByTen() //returns a value of 10
incrementByTen() //returns a value of 20
  • incrementByTen에는 makeIncrementer가 만들어준 runningTotal에 10씩 늘려주는 incrementer 클로저를 저장하게 된다.

  • 그냥 생각해보면 makeIncrementer가 끝난 후엔 runningTotalamount는 사라져야 하는데, 사라지지 않고 클로저가 계속 이용하고 있다.

  • 그 이유가 바로 incrementByTen에 저장된 클로저가 runningTotal을 참조하고 있기(RC를 하나 늘려주고 있기) 때문이다.

  • 여러번 불러도 runningTotal 값이 0으로 초기화되지 않고 그냥 10씩 늘어나는 것도 incrementByTen이 동일한 변수를 참조하고 있기 때문이다.

  • 만약 처음에 생각했던대로 잡아두는 방식이 아니라 환경을 사진처럼 찍어두는 것이었다면, runningTotal의 값은 실행할 때마다 0으로 시작했을 것이다.




이스케이핑 클로저(escaping closure)

  • 어떤 함수의 내부에 존재하는 클로저(함수)를 외부 변수에 저장하는 경우
var defaultFunction: () -> () = { print("출력") }

func escapingFunc(closure: @escaping () -> ()) {
		// 클로저를 실행하는 것이 아니라  defaultFunction 변수에 저장. 
		// 함수는 변수와 달리 기본적으로 외부 할당이 불가능
    defaultFunction = closure        
}
  • 클로저가 실행되는 순서를 보면
    1. 클로저가 escapingFunc() 함수의 closure 인자로 전달됨
    2. 클로저 closure이 defaultFunction 변수에 저장됨
    3. escapingFunc() 함수가 값을 반환하고 종료됨
    4. 클로저 closure은 아직 실행되지 않음


  • closure은 함수의 실행이 종료되기 전에 실행되지 않기 때문에 escaping 클로저, 다시말해 함수 밖(escaping)에서 실행되는 클로저 입니다.
profile
Hello

0개의 댓글