[Swift] 클로저 (Closure)

김상우·2021년 10월 29일
0

클로저 (Closure)

  • 클로저는 사용자의 코드 안에서 전달되어 사용할 수 있는, 로직을 가진 중괄호 { }로 구분된 코드의 블럭이며, 일급 객체의 역할을 할 수 있다.

  • 일급 객체는 전달 인자로 보낼 수 있고, 변수 / 상수 등으로 저장하거나 전달할 수 있으며, 함수의 반환 값이 될 수도 있다.

  • 클로저는 보통 익명 함수를 말한다.
    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

후행 클로저 (trailing closure)

  • 맨 마지막 매개변수로 전달 되는 클로저는 후행 클로저 기능을 사용할 수 있다.

  • 매개변수가 클로저 단 한 개인 경우의 후행 클로저 사용

// 클로저를 매개변수로 받는 함수
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
}
profile
안녕하세요, iOS 와 알고리즘에 대한 글을 씁니다.

0개의 댓글