클로저를 얼마나 다양하게 표현할 수 있는지 보자
- 클로저는 매개변수와 반환 값의 타입을 문맥을 통해 유추할 수 있기 때문에 매개변수와 반환 값의 타입을 생략할 수 있다.
- 클로저에 단 한 줄의 표현만 들어있다면 암시적으로 이를 반환 값으로 취급한다.
- 축약된 전달인자 이름을 사용할 수 있다.
- 후행 클로저 문법을 사용할 수 있다.
스위프트의 클로저는 C언어나 Objective-C의 브록(block) 또는 다른 프로그래밍 언어의 람다(lambda)와 유사, 클로저는 일정 기능을 하는 코드를 하나의 블록으로 모아놓은 것을 말하며 함수와 비슷하며 함수 역시 클로저의 한 형태.
클로저의 세 가지 형태.
- 이름이 있으면서 어떤 값도 획득하지 않는 전역함수의 형태
- 이름이 있으면서 다른 함수 내부의 값을 획득할 수 있는 중첩된 함수의 형태
- 이름이 없고 주변 문맥에 따라 값을 획득할 수 있는 축약 문법으로 작성한 형태
예]
스위프트 라이브러리의 sorted(by:) 메서드 정의
public func sorted(by areInIncreasingOrder: (Element, Element) -> Bool) -> [Element]
//정렬에 사용될 이름
let names : [String] = ["wizplan", "eric", "yagom", "jenny"]
//정렬을 위한 함수 전달
func backwards(first: String, second: String) -> Bool {
print("\(first) \(second) 비교중")
return first > second
}
let reversed: [String] = names.sorted(by: backwords)
print(reversed)
//["yagom", "wizplan", "jenny", "eric"]
위의 코드들을 클로저 표현을 사용해 좀 더 간결하게 표현.
클로저 표현은 통상 아래 형식을 따른다.
{ (매개변수들) -> 반환 타입 in
실행코드
}
클로저는 매개변수 기본 값을 사용할 수 없으며 입출력 매개변수를 사용하고 매개변수 이름을 지정한다면 가변 매개변수 또한 사용 가능.
//backword(first:second:) 함수 대신에 sorted(by:) 메서드의 전달인자로 클로저를 직접 전달
let reversed: [String] = names.sorted(by: { (first:String, secode:String) -> Bool in
return first > second
}
위의 func backwards(first:second)와 아래 sorted(by:)로 전달되는 인자는 동일하다. 이럴 경우 func backwards가 어디에 구현되어 있는지 찾아다니지 않아도 되므로 편하지만 여러번 동일하게 중복되는 기능일 경우 함수로 구현해 두는 것도 한 방법이다.
후행 클로저
함수나 메서드의 마지막 전달인자로 위치하는 클로저는 함수나 메서드의 소괄호를 닫은 후 작성 가능, 클로저가 길어지거나 가독성이 떨어진다 싶을 때 후행 클로저 기능을 사용하면 좋다. 하지만 후행 클로저는 맨 마지막 전달인자로 전달되는 클로저에만 해당 되므로 전달 인자로 클로저 여러 개를 전달 할 때는 맨 마지막 클로저만 후행 클로저로 사용 가능.
sorted(by:)메서드처럼 단 하나의 클로저만 전달인자로 전달하는 경우에는 소괄호를 생략 가능.
후행 클로저 표현
//후행 클로저의 사용
let reversed: [String] = names.sorted() { (first:String, second: String) -> Bool in
return first > second
}
//sorted(by:) 메서드의 소괄호까지 생략 가능.
let reversed: [String] = names.sorted { (first:String, second:String) -> Bool in
return first > second
}
//암시적 생략을 위해서 다음과 같이도 된다. ㅎㅎ
let reversed: [String] = names.sorted {$0 > $1}
//위의 예는 클로저 표현 간소화의 극강을 보여주는 예
클로저 문법의 in 은 매개변수 및 반환 타입과 실행 코들르 구분하기 위해 사용한다. 간결할하게 표현할 때는 in도 생략 가능하다.
<연산자의 정의>
public func > <T : Comparable>(lhs: T, rhs: T) -> Bool
함수 > 자체가 함수의 이름인데 (자바스크립트 jQuery의 $ 같은 식?) 이 함수는 전달인자로 보내기에 충분한 조건을 갖고 있다.
//연산자 함수를 클로저의 역할로 사용
let reversed: [String] = names.sorted(by: >)
값 획득.
반환 타입 () -> Int는 함수객체를 반환한다는 의미. 반환하는 함수는 매개변수를 받지 않고 반환 타입은 Int인 함수로, 호출할 때마다 Int 타입의 값을 반환해준다.
값 획득 부분은 읽어보면 대략적으로는 이해가 가는데 정확하지않아 따로 정리하지 않음. 단 변수나 인자의 값의 범위가 소괄호를 내에서 유효한 점에 비추어 보자면 클로저를 포함하는 함수안의 변수나 인자의 값을 참조해서 가지고 있을 수 있는 클로저의 로직을 수행할 수 있다는 점에 대해서는 이해를 하였다.
'프로그래밍 > Swift' 카테고리의 다른 글
UILabel Size Animation With layer.anchorPoint (0) | 2021.07.05 |
---|---|
@escaping (0) | 2020.11.12 |
@objc (0) | 2020.11.12 |
Swift의 where절 (0) | 2020.11.12 |
Swift ForEach 사용 예 (0) | 2020.11.12 |