Introduce

  • 클로저가 주변 context를 통해 상수 및 변수 값을 클로저 내부에서 사용하면, 그 값을 그대로 사용하지 않고 별도의 참조를 획득해서 사용한다.
  • Context는 클로저 내부 코드가 실행되기 위해 필요한 환경을 의미한다.

Value Capture

  • 클로저 외부 값이 더 이상 존재하지 않더라도 항상 클로저를 실행시킬 수 있도록 클로저 내부에 별도의 변수로 할당해 두고 사용한다. 때문에, 획득한 값을 변경하더라도 클로저를 실행할 때는 클로저가 생성될 당시의 값이 적용된다.
func createIncrement(value: Int) -> (() -> Int) {
  var total = 0
  let increment = { () -> Int in 
                    total += value        // capture total(0)
                    return total
                  }
  return increment
}

let incrementByOne: () -> Int = createIncrement(value: 1)
print(incrementByOne())        // 1
print(incrementByOne())        // 2
print(incrementByOne())        // 3
  • createIncrement 실행이 끝나면서 total 변수와 value 인자는 메모리에서 해제되었지만, 반환된 클로저 안에서 사용되는 totalvalue 변수는 미리 획득해둔 값을 사용한다.
  • incrementByOne()을 실행할 때 마다 capture된 total에 caputre된 value를 더한 결과가 반환된다.

Closure Type

  • 클로저도 클래스 인스턴스처럼 참조 타입이므로 여러 변수가 하나의 클로저를 참조할 수 있다.
  • incrementByOneanotherIncrement는 같은 클로저를 참조하므로 실행 결과가 동일하다.
  • incrementByTwoincrementByOne과 다른 클로저를 생성해서 할당했으므로 실행 결과가 다르다.
    let incrementByOne: () -> Int = createIncrement(value: 1)
    let anotherIncrement: () -> Int = incrementByOne
    let incrementByTwo: () -> Int = createIncrement(value: 2)
    print(incrementByOne(), anotherIncrement())        // 1, 1
    print(incrementByOne(), anotherIncrement())        // 2, 2
    print(incrementByOne(), anotherIncrement())        // 3, 3
    print(incrementByTwo())        // 2
    print(incrementByTwo())        // 4
    print(incrementByTwo())        // 6