Swift: Closure

장일규·2021년 12월 16일
0

Closure Expression Syntax (클로저 표현식 구문 표현)

  • 익명 함수인 만큼 func라는 키워드를 사용하지 않는다.
  • closure는 Closure HeadClosure Body를 가지고 있고, in을 통해서 구분한다.

image

Parameter와 Return Type이 둘 다 없는 closure

closure는 함수이름이 없는 익명이지만, 익명 함수이다.

1급 객체의 특성을 살려서 상수/변수에 클로저를 대입할 수 있다.

    let hello = { () -> () in
        print("Hello")
    }
    hello() // hello

Parameter와 Return Type이 있는 클로저

    let hello2 = { (name: String) -> String in
        return "Hello, \(name)"
    }

parameter Name이 단독으로 쓰였다고, Arguemnt Label이자 Parameter Label이라고 생각할 수 있겠지만, closure에서는 Argument Label을 사용하지 않는다.

오직 parameter Name만 사용된다.

    hello2(name: "장일규") // error
    hello2("장일규")

파라미터가 있는 함수를 호출할 때 일반함수 호출하듯이 Argument Label을 적고 파라미터 값을 넘겨주면 에러가 난다.

클로저는 함수의 파라미터 타입으로 클로저를 전달할 수 있다.

    func doSomething(closure: () -> ()) {
        closure()
    } 

doSomething함수의 parameter로 closure가 정의가 되어있다.

parameter에 우리가 알고 있는 일반적인 함수를 넘길 수도 있지만, 아래 코드와 같이 클로저를 넘길 수 도 있다.

    doSomething(closure: { () -> () in
        print("closure")
    })

함수의 반환 타입으로 클로저를 사용할 수 있다.

    func doSomething2() -> (Int) -> () {
        return { (age: Int) -> () in
            print("I'M \(age)")
        }
    }

    doSomething2()(29)

위와 같이 클로저를 리턴할 수도 있다.

    let ageClosure: (Int) -> () = doSomething2()

    ageClosure(19)

호출하는 곳에서 클로저를 받아서 실행할 수도 있다.

Trailing Closures (트레일링 클로저)

클로저 표현식을 함수의 최종 인자로 전달해야 하는데 그 클로저 표현식이 아주 길 경우, 이 대신 트레일링 클로저 (trailing closure) 를 작성하는 것이 유용할 수 있다.

'트레일링 클로저’ 는, 여전히 함수의 인자이면서도, 함수 호출 괄호 뒤에 작성한다.

    func someFunctionThatTakesAClosure(closure: () -> Void) {
        closure()
    }

위에 someFunctionThatTakesAClosure함수와 같이 클로저 한개만 파라미터로 받는 함수가 있을때 함수를 호출하기 위해서

    // 다음은 이 함수를 '트레일링 클로저'를 사용하지 않고 Inline Closure로 호출하는 방법

    someFunctionThatTakesAClosure(closure: {
        // 클로저 본문은 여기에 둔다.
        print("Hello!")
    })

위에 코드와 같이 작성했다.

클로저가 파라미터의 값 형식으로 함수 호출되는 인자값 인 괄호()안에 작성되어 있는 것Inline Closure라고 한다.

클로저를 파라미터의 값 형식으로 전달하는 것이 아닌 함수의 가장 마지막에 클로저를 꼬리처럼 덧붙여서 사용할 수있다.

1.파라미터가 클로저 하나인 함수

  1. 파라미터에 클로저 단 한개만 있을 경우에는 이 클로저는 첫 파라미터이자 마지막 파라미터이므로 트레일링 클로저가 가능하다. 또한, 호출 구문인 괄호 ()도 생략할 수 있다.

  2. 'closure'라는 ArgumentLabel은 트레일링 클로저에선 생략된다.

    // 다음은 이 함수를 트레일링 클로저로 호출하는 방법

    someFunctionThatTakesAClosure() { () -> () in
    // 끝자리 클로저 본문은 여기에 둡니다.
    }

2.파라미터가 여러 개인 함수

    func doSomething2(success: () -> (), fail: () -> ()) {
        // 함수 본문
        success()
        fail()
    }

위에 doSomething2함수는 success와 fail 두개의 클로저를 매개변수로 가지고 있는 함수이다.

    // 다음은 이 함수를 '트레일링 클로저'를 사용하지 않고 Inline Closure로 호출하는 방법
    doSomething2(success: { () -> () in
        print("Success!")
    }, fail: { () -> () in
        print("Fail!")
    })

위에 코드는 Inline Closure로 호출하는 코드이다.

    doSomething2(success: {
        () -> () in
        print("Success!")
    }){ () -> () in
        print("Fail")
    }

위에 코드 처럼 마지막 파라미터의 클로저는 함수 뒤에 붙여서 사용할 수 있다.

단, 여러개의 파라미터가 있을 경우에는 함수 호출 괄호()를 생략할 수 없다.

클로저 경량 문법

문법을 최적화하여

    func doSomething3(closure: (Int,Int,Int) -> Int) {
        closure(1,2,3)
    }

doSomething3함수는 매개변수로 closure를 받고 있다.

closure에 매개변수로 Int 3개를 받고 있고, Int타입을 반환한다.

doSomething3함수 내부에서는 매개변수로 받은 closure를 실행하는데 closure에 매개변수로 1,2,3을 넘겨준다.

    doSomething3(closure: { (a: Int,b: Int,c: Int) -> Int in
        return a+b+c
    })

위에 호출부는 Inline Closure방식으로 작성한 코드이다.

위에 코드를 아래와 같이 줄일 수 있다.

파라미터 형식과 리턴 형식을 생략할 수 있다.

    doSomething3(closure: { (a, b, c) in
        return a+b+c
    })

상수의 타입인 : Int와 return(반환)타입인 Int를 생략하였다.

Parameter Name을 Shortand Argument Names으로 대체하면, Parameter Name과 in 키워드를 삭제할 수 있다.

Shortand Argument Names은 Parameter Name(매개변수 이름) 대신 사용할 수 있는 것이다.

    doSomething3(closure: {
        return $0 + $1 + $2
    })

매개변수 이름 대신

a -> $0

b -> $1

c -> $2

$ 와 접근하고자 하는 index를 나타내는 숫자로 순서대로 접근 할 수 있다.

단일 리턴문만 남을 경우, return도 생략한다

    doSomething3(closure: {
        return $0 + $1 + $2
    })

위와 같이 코드 내부에 return문 하나만 있을 경우 return 키워드도 생략 할 수 있다.

```swift
    doSomething3(closure: {
         $0 + $1 + $2
    })

return문을 생략한 코드이다.

클로저 파라미터가 마지막 파라미터일 경우 트레일링 클로저로 작성한다

    doSomething3() {  
        $0 + $1 + $2
    }

트레일링 클로저를 활용해 파라미터 마지막이 클로저일 경우 위와 같이 줄일 수 있음

()에 값이 아무 것도 없다면 생략할 수 있다

doSomething3 {  
    $0 + $1 + $2
}

0개의 댓글

관련 채용 정보