스위프트에서 클로저라는 기능은 일회용 함수를 작성할 수 있는 구문이다.
작성방식은 워낙에 다양하지만 일회용으로 함수를 작성하다 보니 함수명이 필요 없어 익명함수라고 부르기도 한다.
클로저는 이미 다른 언어들에도 존재하는 기능인데, 다른 언어에서는 다음과 같이 부른다.
자바스크립트 - 익명함수
자바 - 람다함수
파이썬 - 람다함수
아마 대충 어떤 내용이 나올지 예상이 될 것이다.
원래 클로저 자체는 세 가지를 의미한다.
• 전역함수
• 중첩함수
• 클로저 표현식
여기서 살펴볼 내용은 클로저 표현식에 중점을 둘 것이다.
클로저의 표현식
우선 클로저는 기본적으로 함수이기 때문에 함수의 기본적인 형태를 따르나
일회용이기 때문에 많은 부분이 생략된다. 차차 알아가 보자.
//기본적인 형식
{ (매개변수) -> 반환형 in
실행 구문
}
//인자값, 반환값 없을때
{ () -> () in
실행 구문
}
우선 func 키워드가 생략됐고 중괄호 안에 처음에 내용이 전부 들어간다.
특이한 점은 함수 작성 시엔 반환값이 없어도 정상적으로 작성 가능하지만
클로저는 반환값이 없어도 가독성을 위해 반드시 빈 소괄호나 Void
를 작성해야 한다.
클로저는 여러 가지 방법으로 실행할 수 있다.
//기본적인 실행방식
let abc = { (num: Int) -> () in
print(num+1)
}
abc(2) // 3 출력
//한번 더 간소화
({ () -> () in
print("실행됨.")
})() // 실행됨. 출력
첫 번째를 보면 매개변수명을 써도 함수 내부에서만 사용하는데
이는 간소화를 해도 똑같이 적용된다.
후행 클로저(트레일링 클로저; Trailing Closure)
후행(트레일링) 클로저는 함수의 마지막 인자값이 클로저일 때, 인자값 형식으로 작성하지 않고
함수 뒤에 꼬리처럼 붙이는 것을 의미한다.
일단 예시를 보자.
var arr = [4, 2, 5, 1, 3]
//아래처럼 클로저가 있다고 할 때
arr.sorted(by: {(s1, s2) in
return s1 > s2})
⬇︎⬇︎⬇︎⬇︎⬇︎⬇︎⬇︎⬇︎⬇︎⬇︎⬇︎
arr.sorted() { (s1, s2) in
return s1 > s2
}
⬇︎⬇︎⬇︎⬇︎⬇︎⬇︎⬇︎⬇︎⬇︎⬇︎⬇︎
arr.sorted(by: >)
클로저를 꼬리로 따로 붙이고 함수의 괄호를 생략까지도 할 수 있다.
탈출 클로져(Escaping Closures)
우선 예시를 하나 보자.
func callback(fn: () -> ()) {
fn()
}
callback {
print("Closure 실행됨.")
}
위의 예시는 callback함수를 후행 클로저를 이용해 간단하게 만들어
print함수를 callback 함수 내부에서 클로저로 사용한 것이다.
하지만 이를 아래처럼 바꾸면 주석처럼 오류가 발생한다.
func callback(fn: () -> ()) {
let abc = fn // Non-escaping parameter'fn' may only be called
abc()
}
callback {
print("Closure 실행됨.")
}
fn이 non-escaping 파라미터라 직접 호출하는 것만 가능하다는 뜻으로
상수에 대입도 할 수 없는 것이다. 따라서 아래와 같이 @escaping 속성을 타입 앞에 붙인다.
func callback(fn: @escaping () -> ()) {
let abc = fn
abc()
}
callback {
print("Closure 실행됨.") // 정상적으로 "Closure 실행됨." 출력된다.
}
탈출 클로저는 주로 비동기로 작동해야 할 부분들에 사용된다.
자동 클로저(Autoclosures)
자동 클로저는 인자값으로 전달된 구문들을 클로저로 래핑(Wrapping)한다.
이 말인 즉, 인자값으로 전달된 구문을 알아서 클로저로 만들어 준다는 것이다.
실제로는 지연된 동작방식이 필요할 때 사용한다.
선언 방식은 위의 탈출 클로저처럼 타입 앞에 @autoclosure
를 붙여주면 된다.
우선 다음의 예시를 보자.
// 빈 배열 정의
var arr = [String]()
func addVars(fn: @autoclosure () -> Void) {
// 배열 요소를 3개로 만들어 초기화
arr = Array(repeating:"", count: 3)
// 인자값으로 전달된 클로저 실행
fn()
}
arr.insert("KR", at: 1) // 오류 발생
addVars(fn: arr.insert("KR", at: 1)) // 정상 실행
// 출처 - 꼼꼼한 재은씨의 스위프트:문법편
위의 예시를 보면 알겠지만 arr를 분명히 초기화한 것 같지만 13번째 줄에서 오류가 발생한다.
이유는 간단하다. 함수가 작성되고 실행되지 않았기 때문에 안의 구문은 아직 실행이 되지 않았고
15번째 줄에서 실제로 함수가 호출되어 실행될 때 초기화 또한 하기 때문에
그제야 정상적으로 실행되는 걸 볼 수 있다.
스위프트 문법 - 클로저, Closure, swift
'공부 > Apple' 카테고리의 다른 글
[스위프트] 구조체(Struct)와 클래스(Class) - 공통점과 차이점 (0) | 2023.08.16 |
---|---|
[스위프트] 델리게이트 패턴 (delegate) (0) | 2023.08.06 |
[스위프트] defer(디퍼) (0) | 2023.07.10 |
[스위프트] 함수(파트3) (0) | 2023.07.10 |
[스위프트] 함수(파트1) (0) | 2023.07.09 |