클로저는 {} 형식의 코드블럭 이다.
- 전달인자로 보낼 수 있고, 변수/상수 등으로 저장하거나 전달할 수 있으며, 함수의 반환 값이 될 수도 있다.
- 참조 타입이다.
- 함수는 클로저의 한 형태로 이름이 있는 클로저이다.
- Named Closure : 함수
func doSomething() { print("Somaker") }
- Unnamed Closure : 익명 함수 -> 보통의 Closure
let closure = { print("Somaker") }
Closure의 기본 형식
{ (Parameters) -> return Type in 로직 구현 }
1. 클로저를 변수나 상수에 대입할 수 있다.
let closure = { () -> () in
print("Closure")
}
let closure2 = closure
2. 함수의 파라미터 타입으로 클로저를 전달할 수 있다.
func doSomething(closure: () -> ()) {
closure()
}
doSomething(closure: { () -> () in
print("Hello!")
})
3. 함수의 반환 타입으로 클로저를 사용할 수 있다.
func doSomething() -> () -> () {
return { () -> () in
print("Hello!")
}
}
Closure의 축약(간소화)
: Closure는 메서드에서 요구하는 형태로 전달해야 한다.
(매개변수 타입이나 개수, 반환 타입이 같아야 전달인자로서 전달 가능) -> 이 규칙 때문에 타입 유추가 가능해진다.
- 타입 생략
let reversedNames = names.sorted(by: {s1, s2 in return s1 > s2})
: sorted(by:)의 경우는 이미 (String, String) -> Bool 타입의 인자가 들어와야 되는지 알고 있기 때문에 클로저에서 타입을 명시하는것을
생략할 수 있다.
- 반환타입 생략
let reversedNames = names.sorted(by: {s1, s2 in s1 > s2})
: 반환 키워드를 생략할 수 있다.
- 인자 이름 생략
let reversedNames = names.sorted(by: { $0 > $1 })
: 인자 값을 축약해서 사용할 수 있다. (인자의 표기는 $0부터 순서대로)
- 연산자 메서드
let reversedNames = names.sorted(by: > )
: 연산자를 사용할 수 있는 타입의 경우 연산자만 남길 수 있다.
후행 클로저
: 클로저에 여러 줄의 표현(실행코드)이 들어가게 된다면 후행 클로저를 사용하여 함수의 뒤에 표현할 수 있다.
* 마지막 전달 인자로 전달되는 클로저만 해당됨.(맨 마지막 클로저만 후행 클로저 사용 가능)
let reversedNames = names.sorted() { $0 > $1 }
- 함수의 마지막 인자가 클로저 이고, 후행 클로저를 사용하면 괄호"()"를 생략할 수 있다.
let reversedNames = names.sorted { $0 > $1 }
Escaping Closure
: 클로저가 함수의 인자로 전달되지만 함수 밖에서 실행되는 것(함수가 반환된 후 실행되는 것)을 Escape 한다고 하며,
이러한 경우 매개변수 타입 앞에 @escaping이라는 키워드를 명시해야 한다.
함수 사이에 실행 순서를 정할 수 있다.
> 자주 사용되는 경우
- 비동기로 실행되는 경우
- completionHandler(완료에 따른 처리)로 사용되는 클로저의 경우
@escaping을 사용하는 클로저에서는 self를 명시적으로 언급해야 한다.
func test(completionHandler: @escaping () -> Void) {
completionHandler()
}
Auto Closure
: 인자 값이 없으며, 특정 표현을 감싸서 다른 함수에 전달 인자로 사용할 수 있는 클로저를 말한다.
자동 클로저는 클로저를 실행하기 전까지 실제 실행이 되지 않는다.
즉, 실제 계산이 필요할 때 호출이 되기 때문에 계산이 복잡한 연산을 하는데 유용하다.
var customersInLine = ["A", "B", "C", "D", "E"]
print(customersInLine.count) // 5
let customerProvider = { customersInLine.remove(at: 0) } //해당 코드가 지나도 count가 줄지 않는다.
print(customersInLine.count) // 5
// customerProvider가 실행되었을때만 동작
print(" Now serving \(customerProvider())!") // "Now serving A!"
print(customersInLine.count) // 4
자동 클로저를 함수의 인자값으로 넣는 예제 (매개변수 타입 앞에 @autoclosure이라는 키워드를 사용한다)
// customerInLine is ["F", "G", "H"]
func serve(customer customerProvider: @autoclosure () -> String) {
print("Now serving \(customerProvider())!")
}
serve(customer: customerInLine.remove(at: 0) // "Now serving F!"
@autoclosure는 @escaping과 같이 사용할 수 있다.
출처 : https://medium.com/@jgj455/%EC%98%A4%EB%8A%98%EC%9D%98-swift-%EC%83%81%EC%8B%9D-closure-aa401f76b7ce
https://axe-num1.tistory.com/18
'iOS > Swift' 카테고리의 다른 글
UIWebView 와 WKWebView 차이 (0) | 2021.12.12 |
---|---|
[Swift] Array, Dictionary, Set, Tuple (0) | 2021.12.12 |
[Swift] 메모리를 참조하는 방법 (Strong, Weak, Unowned) (1) | 2020.07.30 |
[Swift] Type Casting (0) | 2020.07.29 |
[Swift] Class 와 Struct (0) | 2020.07.03 |