이번 시간에는 Capture List에 대해서 알아보도록 할게요
먼저 클로저는 주변 범위에서 변수나 상수를 강한 참조로 캡처할 수 있는 건 다들 아시죠? ㅎ
캡처 리스트의 기본 개념에 대해서 먼저 알아보도록 할게요
- 클로저 안에서 캡처된 변수들이 어떻게 컨트롤할지 명확하게 하기 위해서 사용되어요
- 매개변수의 리스트 앞에 대괄호로 둘러 싸여서 콤마로 분리되어서 쓰입니다
- 사용한다면 매개변수의 이름이나 매개변수 타입이나 반환 타입을 생략할 지라도 반드시 in 키워드를 사용해야 해요
- 진입점은 클로져가 생성되었을 때이다
- 캡처 목록의 각 항목에 대해 상수는 주변 범위에서 이름이 같은 상수 또는 변수의 값으로 초기화된다.
아래에 코드를 보면서 추가적으로 설명드릴게요!
var a = 0
var b = 0
let closure = { [a] in
print(a, b)
}
a = 10
b = 10
closure()
//print 0 10
먼저 코드에서 변수 a와 b가 존재하고 캡처 리스트 안에 a를 담았는데
이렇게 되었을 때 closure를 실행하게 되면 b만 바뀌어져 있는 것을 확인할 수 있어요
이게 왜 그렇냐면 캡처 리스트에 담겨서 클로저 내부에서 사용된 순간부터 a는 처음 밖에서 초기화된 값을 가지고 내부에서 사용되고 매개변수와 같이 상수로 사용되기 때문이에요
그리고 내부에서 사용된 a와 외부에서 사용되어진 a는 아무런 관계가 없습니다
그러므로 외부에서 a가 바뀌더라도 내부에 영향을 주지 못하고 내부에서 a를 바꿔도 외부에 영향을 줄 수가 없다
대신 b는 외부에서 바뀌면 내부에 b도 영향을 받게 됩니다
아래에 코드를 한번 볼게요
class SimpleClass {
var value : Int = 0
}
var x = SimpleClass()
var y = SimpleClass()
let closure = { [x] in
print(x.value, y.value)
}
x.value = 10
y.value = 10
closure()
이 코드는 위에 나온 코드와는 다르게 x의 값을 켭쳐리스트에 담아서 클로저 내부에서 사용했지만
변수 x의 value프로퍼티에 값을 변경했더니 값이 변경된 것을 확인할 수 있는데
그 이유는 외부에 선언된 x나 캡처 리스트 내부에 있는 x나 둘 다 똑같은 곳을 참조하고 있기 때문에 위의 코드처럼 작동하게 돼요
캡처 리스트의 타입이 class라면 weak나 unowned 참조로 만들 수 있다
1) myFunction { print(self.title) }
//implicit strong capture
2) myFunction { [self] in print(self.title) }
//explicit strong capture
3) myFunction { [weak self] in print(self!.title) }
//weak capture
4) myFunction { [unowned self] in print(self.title) }
//unowned capture
위의 코드처럼 클래스나 구조체 내부 closure에서 self를 사용하는데
1)처럼 사용하게 되는데 그러면 자연적으로 강한 참조를 하게 되고
2)처럼 사용하면 외부적으로 강한 참조를 하겠다고 보여주는 것이고
3)처럼 사용하면 weak 참조로 self를 사용하겠다는 것이고
4)처럼 사용하면 unowned로 self를 사용하겠다는 것이다
캡쳐 리스트에서 값의 이름을 임의적인 표현으로 바인드 할 수 있는데 방법을 보여드리도록 할게요
클로져가 생성될 때에 표현이 평가된다 그리고 그 값은 특정한 영향력을 가지게 돼요
class MyClass {
var type : String = "peachberry"
func Function() {
myFunction { [weak type = self.type] in
print(type)
}
}
}
위와 같이 코드를 작성하면 이런 에러를 만날 수 있다
왜냐하면 임의의 표현을 바인드 할 수 있지만 프로토콜 타입이나 클래스 타입만 가능하다 String은 구조체여서 불가능하다
class MyType {
var name : String = "peachberry"
}
class MyClass {
var type : MyType?
func Function() {
myFunction { [weak mytype = self.type] in
print(mytype?.name)
}
}
}
func myFunction(closure : () -> Void) {
closure()
}
var x = MyClass()
x.Function()
이렇게 코드를 작성하여주면 문제없이 작동하는 것을 볼 수 있다
여기까지가 capture list에 관한 내용이었습니다! ㅎ
끝까지 읽어주셔서 감사합니다! :)
부족한 부분이 있거나 틀린 부분이 있으면 지적해주시면 감사하겠습니다
'Swift' 카테고리의 다른 글
Swift - Properties - Property Wrappers (0) | 2020.07.21 |
---|---|
Swift - Protocols Method 요구사항 (0) | 2020.03.12 |
Swift - Protocols Property 요구사항 (0) | 2020.03.08 |
Swift - Protocols 기본개념 (0) | 2020.03.07 |