[Swift] Closure - 2 (Capturing)

728x90

Capturing에 대해 알아 보겠습니다.

 

CaptureList

클로저는 정의 된 주변 컨텍스트에서 상수 및 변수를 캡처(Capturing) 할 수 있습니다.
그런 다음 클로저는 상수와 변수를 정의한 원래 범위가 더 이상 존재하지 않더라도 본문 내에서 해당 상수와 변수의 값을 참조하고 수정할 수 있습니다.

 

Value Type Capture

var a = 1
var b = 2
var c = 3
var result = 0

// 1,2,3,0
print("초기화 값 :", a, b, c, result)
print("a, b 만 캡쳐")
let valueCapture = { [a,b] in
    result = a + b + c
    print("내부 : ", result)
}

//1번째 호출
valueCapture() // 내부 6

a = 2
b = 3
c = 4
result = a + b + c
print("변경 값 :", a, b, c, result)

//2번째 호출
valueCapture() // 내부 7

valueCapture클로저에서 []을 이용하여 a, b를 값을 캡처했습니다.

1번째로 valueCapture를 호출했을때 내부 값은 6으로 나왔고, a,b,c의 값을 변경 후 2번째로 valueCapture를 호출했을때 a,b는 여전히 1,2로 캡처되어있고 c변수만 4로 변경되어져 내부 값이 7로 변경되어진걸 볼 수 있습니다.

 

Reference Type Capture

클로저는 기본적으로 Reference Type입니다.
클로저 바깥의 값을 사용할 때는 해당 값을 참조하여 사용하게 됩니다.

final fileprivate class RefType {
  var number = 0
}
fileprivate var x = RefType()
fileprivate var y = RefType()
print("초기화 값 :", x.number, y.number)

let refCapture = { [x] in
  print("클로저 내부 값 :", x.number, y.number)
}

x.number = 5
y.number = 7
print("변경 값 :", x.number, y.number)

refCapture()
print("실행 이후 값 :", x.number, y.number)


초기화 값 : 0 0
변경 값 : 5 7
클로저 내부 값 : 5 7
실행 이후 값 : 5 7

refCapture는 [x]를 캡처하고 있음에도 불구하고,
클로저 내부 x.number, y.number 외부 x.number, y.number를 참조하고 있습니다.
이러한 Reference Type의 특성으로인해 원치않는 값의 변화가 생길 수 있습니다.

 

Binding an arbitrary expression

let captureBinding = { [z = x] in
  print(z.number)
}
let captureWeakBinding = { [weak z = x] in
  print(z?.number ?? 0)
}
let captureUnownedBinding = { [unowned z = y] in
  print(z.number)
}

captureBinding() // 5
captureWeakBinding() // 5
captureUnownedBinding() // 7

'Swift' 카테고리의 다른 글

[Swift] 타입체크(TypeCheck)  (0) 2019.07.22
[Swift] Closure - 3 (NoEscaping, Escaping, AutoClosure)  (0) 2019.07.22
[Swift] Closure - 1 (Basic)  (0) 2019.07.22
[Swift] 옵셔널(Optionals)  (0) 2019.07.22
[Swift] 접근제어(Access Control)  (0) 2019.07.20