개발 일기

Closures ? 본문

컴퓨터 언어/swift

Closures ?

이건욱

Closures

"Closures are self-contained blocks of functionality that can be passed around and used in your code"

클로저는 코드의 블럭이고 주변에 넘길수도 있고 사용할수도 있습니다.

클로저는 선언 되었을 때 상수와 변수를 Context로 부터 References을 저장을 합니다.

 

클로저는 최적화를 통해서 clean , clear style을 표현할수가 있으며 다음을 포함하고 있습니다.

 

  • Inferring parameter and return value types from context

  • Implicit returns from single-expression closures

  • Shorthand argument names

  • Trailing closure syntax

Closure Expression Syntax

기본적인 사용방법은 다음과 같습니다.

{ (parameters) -> return type in
    statements
}

먼저 클로저는 IN이라는 키워드를 통해서 클로저함수에 매개변수와 Return type이 끝나고 바디가 실행되는것을 나타냅니다.

[예시]

func backward(_ s1: String, _ s2: String) -> Bool {
    return s1 > s2
}
var reversedNames = names.sorted(by: backward)


-----------


reversedNames = names.sorted(by: { (s1: String, s2: String) -> Bool in
    return s1 > s2
})

 

Inferring Type From Context

클로저는 다음과 같이 타입을 유추(파라미터 타입 , Return Type)를 통해서 다음과 같이 생략을 할수가 있습니다.

하지만 타입을 적는것이 유지보수 하는 데에 있어서 필요하다면 사용을 권장합니다!.

reversedNames = names.sorted(by: { s1, s2 in return s1 > s2 } )

 

Implicit Returns from Single-Expression Closures

클로저는 그리고 Return 하는 것도 생략을 할수가 있습니다.

reversedNames = names.sorted(by: { s1, s2 in s1 > s2 } )

 

Shorthand Argument Names

클로저에서는 이름을 자동적으로 매개변수 이름을 제공합니다. ( $0, $1, $2 )

그래서 in이라는 키워드가 필요가 없고 다 유추할수가 있으므로 다음과 같이 표시할수가 있습니다.

reversedNames = names.sorted(by: { $0 > $1 } )

 

Operator Methods

클로저에서 더 짧게 할수는 있습니다.

아래의 내용을 보면 '>' 키워드가 두개의 매개변수 (String) 일때 서로 매개변수를 비교하여 Boolean 값을 Return 하기 때문에 

이렇게 까지 생략을 할수가 있습니다.

reversedNames = names.sorted(by: >)

 

Trailing Closures

함수의 매개변수에 마지막으로 클로저를 넣을 경우에 다음과 같이 표현을 할수가 있습니다.

주의 해야하는 것은 마지막에 {} 

unc someFunctionThatTakesAClosure(closure: () -> Void) {
    // function body goes here
}

// Here's how you call this function without using a trailing closure:

someFunctionThatTakesAClosure(closure: {
    // closure's body goes here
})

// Here's how you call this function with a trailing closure instead:

someFunctionThatTakesAClosure() {
    // trailing closure's body goes here
}

 

Escaping Closures

Escaping Closures을 통해서 함수밖으로 나올수가 있습니다.

따라서 외부 저장소에 저장하거나 다른 쓰레드에서 해당 클로저를 실행을 시키는게 불가하지만 해당 키워드를 통해서 사용이 가능합니다.

 

[예시]

var completionHandlers: [() -> Int] = []


func makeIncrementer(_ amount:  () -> Int){
    completionHandlers.append(amount)
}
makeIncrementer({ 1 })
makeIncrementer({ 2 })
makeIncrementer({ 3 })
makeIncrementer({ 4 })
makeIncrementer({ 5 })
makeIncrementer({ 6 })


for i in completionHandlers {
  print(i())
}

 

위에 부분은 Escaping 클로저가 아닐 경우에 에러가 발생합니다. 왜냐하면 클로저는 밖에서 있는 공간에서 append를 할수가 없기 때문입니다.

 

그래서 다음 같은 부분은 Escaping 클로저가 되어야합니다.

var completionHandlers: [() -> Int] = []


func makeIncrementer(_ amount:@escaping  () -> Int){
    completionHandlers.append(amount)
}
makeIncrementer({ 1 })
makeIncrementer({ 2 })
makeIncrementer({ 3 })
makeIncrementer({ 4 })
makeIncrementer({ 5 })
makeIncrementer({ 6 })


for i in completionHandlers {
  print(i())
}

'컴퓨터 언어 > swift' 카테고리의 다른 글

Enumerations  (0) 2020.06.03
Function ?  (0) 2020.05.16
Control Flow ?  (0) 2020.05.10
Collection Type ?  (0) 2020.05.03
Strings and Characters  (0) 2020.05.01
Comments