iOS/Swift Grammar

[Swift] 클로저(Closure) 기본 클로저와 후행(트레일링) 클로저

kyxxn 2024. 2. 6. 09:57
728x90

클로저 형태

  • 이름이 있으면서 어떤 값도 획득하지 않는 전역함수 형태
  • 이름이 있으면서 다른 함수 내부의 값을 획득할 수 있는 중첩된 함수의 형태
  • 이름이 없고 주변 문맥에 따라 값을 획득할 수 있는 축약 문법으로 작성한 형태

 

  • 공식문서 발췌
1. Global functions are closures that have a name and don’t capture any values.
2. Nested functions are closures that have a name and can capture values from their enclosing function.
3. Closure expressions are unnamed closures written in a lightweight syntax that can capture values from their surrounding context.

클로저 표현 방법 (기본 - 후행)

  • 자신이 정의된 컨텍스트의 변수와 상수에 접근할 수 있는 자체 완결된 기능 블록
  • 클로저는 매개변수와 반환 값의 타입을 유추할 수 있기에 생략 가능
  • 클로저에 단 한 줄의 표현만 있다면, 이를 반환 값으로 취급
  • 축약된 전달인자 이름을 사용할 수 있음
  • 후행 클로저 문법을 사용할 수 있음

 

스위프트 표준 라이브러리 sorted(by:) 메소드로 내림차순하는 방법을 알아보겠음

// 배열 타입과 같은 두 개의 매개변수를 가지며 Bool 타입 반환
// 기본적으로 오름차순 정렬된 배열을 반환함
public func sorted(by areInIncreasingOrder: 
                            (Element, Element) -> Bool) -> [Element]

// 정렬에 사용될 배열
let names = ["Chris", "Alex", "Ewa", "Barry", "Daniella"]

 

클로저를 사용하지 않는 경우

func backward(_ s1: String, _ s2: String) -> Bool {
    return s1 > s2
}
var reversedNames = names.sorted(by: backward)
// reversedNames is equal to ["Ewa", "Daniella", "Chris", "Barry", "Alex"]

s1 문자열이 s2 문자열보다 크다면, 반환값은 true

즉 값이 더 큰 s1 문자열이 s2 문자열보다 앞쪽에 정렬되어야 함

그러나 불필요하게 코드가 많이 사용됨

 

기본 클로저

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

// 혹은

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

타 언어의 익명함수, 람다함수처럼 backward 함수를 따로 생성하지 않고,

클로저를 사용함으로써 코드가 간결해지고, backward 함수를 찾아다니지 않아도 됨

(반복해서 사용할 때는 함수로 구현)

 

후행 클로저 (Trailing Closure)

Xcode 자동완성 시 자동으로 후행 클로저를 유도함

 

후행 클로저의 사용법

  • 맨 마지막 전달인자로 전달되는 클로저에만 해당
  • 즉, 전달인자로 클로저 여러 개를 전달할 때는 맨 마지막 클로저만 가능
  • 단 하나의 클로저만 전달인자로 전달될 경우, 소괄호 생략 가능
  • 매개변수에 클로저가 여러 개인 경우, 다중 후행 클로저 사용가능
    중괄호를 열고 닫음으로써 클로저를 표현
// 후행 클로저의 사용
let reversed: [String] = names.sorted() { (s1: String, s2: String) -> Bool in
    return s1 > s2
}

// sorted(by:) 메소드의 소괄호 생략 가능
let reversed: [String] = names.sorted { (s1: String, s2: String) -> Bool in
    return s1 > s2
}

 

다중 후행 클로저

func doSomeThing(do: (String) -> Void, onSuccess: (Any) -> Void, onFailure: (Error) -> Void) {
        // 실행코드
}

doSomeThing { (someString: String) in
        // 실행코드
} onSuccess: { (result: Any) in
        // 실행코드
} onFailure: { (error: Error) in
        // 실행코드
}

 


참고

https://docs.swift.org/swift-book/documentation/the-swift-programming-language/closures/#Capturing-Values

 

Documentation

 

docs.swift.org

https://babbab2.tistory.com/81

 

Swift) 클로저(Closure) 정복하기(1/3) - 클로저, 누구냐 넌

안녕하세요 :) 소들입니다 으휴 저번 주도 쓸데없이 바빴어서 포스팅을 못했네용 나태한 저번주의 나를 반성하며.. 하암..🥱 음 전에 제가 Swift의 꽃이 Optional이라고 말한 적 있는데, Optional 만큼

babbab2.tistory.com

+ 야곰 스위프트 문법 교재