클로저는 사용자의 코드 안에서 전달되어 사용할 수 있는, 로직을 가진 중괄호 { }로 구분된 코드의 블럭이며, 일급 객체의 역할을 할 수 있다.
일급 객체는 전달 인자로 보낼 수 있고, 변수 / 상수 등으로 저장하거나 전달할 수 있으며, 함수의 반환 값이 될 수도 있다.
클로저는 보통 익명 함수를 말한다.
Named Closure, Unnamed Closure 가 있지만, 보통 Unnamed Closure를 말하는 경우가 많다.함수도 클로저의 한 형태로, 이름이 있는 클로저 이다.
클로저 표현식
{ (매개 변수) -> 리턴 타입 in // 클로저 헤더 실행 구문 // 클로저 바디 }
1. 매개변수와 리턴타입이 없는 클로저
// 매개변수와 리턴타입이 없는 클로저 선언 let hello = { () ->() in print("hello") } // 클로저 호출 hello() // -> hello
2. 매개변수와 리턴타입이 있는 클로저
클로저에서는 전달인자 레이블을 사용하지 않는다.// 매개변수와 리턴타입이 있는 클로저 선언 let hello2 = { (name: String) -> String in return "Hello \(name)" } // hello2(name: "KSW") -> 에러 ! 전달 인자 레이블 사용 금지 print(hello2("KSW")) // -> Hello KSW
3. 함수 매개변수로써의 클로저
클로저는 1급 객체이기 때문에 함수 파라미터로 사용 가능하다.// 클로저는 1급 객체이기 때문에 함수 파라미터로 사용할 수 있다. // 클로저를 함수 매개변수로 사용하기 func doSomething(closure: () -> ()) { closure() } doSomething(closure:{() -> () in print("Do something!")}) // -> Do something!
4. 함수 리턴타입으로써의 클로저
- 클로저 타입이 리턴되기 때문에, 그것을 실행하려면 ()을 한번 더 적어줘야 함.
// 클로저를 리턴하는 함수 func doSomething2() -> () -> () { return { () -> () in print("closure return") } } // 리턴된 클로저 실행 doSomething2()() // -> closure return
맨 마지막 매개변수로 전달 되는 클로저는 후행 클로저 기능을 사용할 수 있다.
매개변수가 클로저 단 한 개인 경우의 후행 클로저 사용
// 클로저를 매개변수로 받는 함수 func doSomething(closure: () -> ()) { closure() } // 기본 클로저 doSomething(closure: { () -> () in print("hello") }) // -> hello // 매개변수와 반환값 모두 없었으므로 모두 생략 가능 doSomething() { print("hello2") } // -> hello2 // doSomething 처럼 매개변수가 단 하나의 매개변수인 경우, // 소괄호도 생략 가능 doSomething { print("hello3") } // -> hello3
- 다중 후행 클로저
// 다중 후행 클로저 // 매개변수로 클로저를 2개 받는다. func doSomething3(success: () -> (), fail: () -> ()){ } // Xcode 자동완성 기능으로 Enter를 두 번치면, // 자동으로 다중 후행 클로저를 완성시켜준다. // 첫번째 클로저는 매개변수 레이블을 생략한다. doSomething3 { //code } fail: { //code }
- 기본 클로저 형태와 최대한 간소화 된 코드를 비교해보면,
코드 길이가 매우 짧아짐을 느낄 수 있음.// 클로저 표현 간소화 // 클로저 매개변수를 받는 함수 func doSomething4(closure:(Int, Int, Int) -> Int){ closure(1,2,3) } // 기본 클로저 형태 doSomething4 (closure: { (a: Int, b: Int, c: Int) in print(a+b+c) return a+b+c }) // -> 6 // 경량 문법 : 파라미터와 리턴타입 생략 가능 // 약식 인수 이름 -> 매개변수 이름 대신에 사용 doSomething4 (closure : { print($0 + $1 + $2) return $0 + $1 + $2 }) // -> 6 // 단일 리턴문만 남았을 경우는 리턴 키워드도 생략 가능. // 위에 print 같은 코드가 있으면 생략 불가능 doSomething4(closure: { $0 + $1 + $2 }) // -> 출력은 되지 않지만 6이라는 값 저장 // 위에서 공부한 후행 클로저 doSomething4 () { $0 + $1 + $2 } // -> 매개변수 생략. 6이라는 값 저장. // 단 하나의 클로저만 매개변수로 전달 되는 경우에는 소괄호도 생략 가능 // 맨 위의 기본 코드와 비교했을 때 길이가 매우 짧아졌음. // (출력하는 기능은 중간에 빼긴 했음) doSomething4 { $0 + $1 + $2 }