클로저는 보통은 익명함수로 인식되지만, 정확하게는 func함수들도 모두 클로저이다. ( 함수도 클로저다 )
클로저는 크게 2가지로 나뉜다.
ㄴ Named Closure
ㄴ Unnamed Closure
func doSomething(){
print("Something")
}
let closure = {
() -> () in
print("Something")
}
이지만 인자도 없고, 반환형도 없으니 윗줄을 모두 날리면
let shortClosure = {
print("Something")
}
이렇게 간단해질 수 있다.
closure() 이렇게 실행할 수 있다.즉시실행함수 IIFE처럼 클로저를 선언과 동시에 바로 호출하고 싶다면(
클로저 본문
)()
을 하면 된다. 반환형도 없고 인자도 없다면
({print("hello")})()
와 같이 될 수도 있다.
클로저에서의 값 캡쳐클로저는 내부 함수와 내부함수에 영향을 미치는 주변 환경을 모두 포함한 객체이다.func doSomething(){
var message = "Hello, nice to meet you!"
let closure = {
() -> () in
print( message );
}
}
클로저에서는 클로저에 영향을 미치는 외부변수도 사용할 수 있다. 이를 값의 캡쳐라고 한다.
클로저의 값 캡쳐방식클로저는 값을 캡쳐할 때 값타입 참조타입에 관계 없이 참조 캡쳐한다. 예시코드를 살펴보면
func doSomething(){
var num : Int = 0
print("\(num)")
let closure = {
() -> () in
print("\(num)")
}
num = 20
print("\(num)")
}
만약에 클로저에서의 캡쳐가 값 캡쳐 였다면, 출력은 0, 0, 20 이 되어야 하는게 맞겠지만 실제 출력은 0, 20, 20 이다.
이는 클로저가 참조 캡쳐를 하기 때문이다.
*만약에 참조 캡쳐가 하기 싫고, 값 캡쳐를 하고 싶다면 이렇게 하면 된다. 자세한 설명은 하단에
let closure = {
[num] in
print("\(num)")
}
이렇게 하면 되고 이렇게 되면 값 캡쳐기 때문에 출력은 0, 0, 20 이 된다.
클로저의 캡쳐리스트let closure = { [num1, num2] in
클로저의 시작인 { 바로 옆에 []을 이용해서 캡쳐할 멤버를 나열한다.
in 키워드는 꼭 들어가야 한다.