본문 바로가기
iOS/Swift

[Swift] 클로저 (Closure)

by 0inn 2022. 9. 24.

클로저(Closure)란 ?

클로저란 func 키워드를 이용해 이름을 붙여주는 함수를 모두 일컫습니다.

클로저에는 Named Closure와 Unnamed Closure 두 가지가 있습니다.

 

1. Named Closure

 

func namedFunc() {
	print("Named Function입니다.")
}

 

Named Closure는 우리가 여태 선언해왔던 이름이 있는 함수로 클로저라 부르지 않고, 함수라고 부릅니다.

 

2. Unnamed Closure

 

let unnamedFunc = { 
	print("Unnamed Func입니다.")
}

 

Unnamed Closure는 익명 함수로 보통 클로저라고 하면 Unnamed Closure를 의미합니다.

 

즉, 클로저는 Named Closure와 Unnamed Closure 둘 다 포함하지만, 보통 익명 함수인 Unnamed Closure를 의미합니다.

클로저 표현식

{ (Parameters) -> Return Type in
	// 실행구문
}

 

- Parameter와 Return Type이 둘 다 없는 클로저

 

let closure = { () -> () in
	print ("Closure입니다.")
}

 

클로저는 익명이긴 하지만 함수이기 때문에 Swift에서 1급 객체입니다.

그러므로 상수에 클로저를 대입할 수 있습니다.

 

- Parameter와 Return Type이 둘 다 있는 클로저

 

let closure = { (name: String) -> String in
	return "Hello, \(name)"
}

closure("0inn")
closure(name: "0inn")	// error

 

함수와 비슷해보이지만 Parameter의 name은 단독으로 쓰였으니 " Argument Label이자 Parameter Name이겠다! " 생각할 수 있겠지만, 클로저에서는 Argument Label을 사용하지 않고 오직 Parameter Name만 사용합니다.

 

Argument Label 이란 ?

func sayHello(to name: String) {
	print ("Hello, \(name)")
}

sayHello(to: "0inn")

이 코드에서 to를 Argument Label 이라고 합니다.

클로저의 특징

앞서 말했듯이 클로저는 1급 객체이기 때문에 1급 객체 함수의 특징을 가지고 있습니다.

 

1. 클로저를 변수나 상수에 대입할 수 있다.

 

// 대입과 동시에 클로저 작성 가능
let closure = { () -> () in
	print("Closure입니다.")
}

// 새로운 변수나 상수에 대입 가능
let newClosure = closure

 

2. 함수의 파라미터 타입으로 클로저를 전달할 수 있다.

 

sayHello(closure: { () -> () in
	print("Hello")
})

 

3. 함수의 반환 타입으로 클로저를 사용할 수 있다.

 

func sayHello() -> () -> () {
	return { () -> () in
    	print("Hello")
    }
}

let closure = sayHello()
closure()  // Hello

클로저 실행

1. 클로저가 대입된 변수나 상수로 호출

 

let closure = { () -> String in
	return "Hello"
}

closure()

 

2. 클로저 직접 실행

 

({ () -> () in
	print("Hello")
})()

트레일링 클로저 (Trailing Closure)

트레일링 클로저란 함수의 마지막 파라미터가 클로저일 때 이를 파라미터 값 형식이 아닌 함수 뒤에 붙여 작성하는 문법입니다.

이 때, Argument Label은 생략됩니다.

 

1. 파라미터가 클로저 하나인 함수

 

func sayHello(closure: () -> ()) {
	closure()
}

// inline Closure 호출 방식
sayHello(closure: { () -> () in
	print("Hello")
})

// trailing Closure 호출 방식
sayHello () { () -> () in
	print("Hello")
}

// 파라미터 하나일 경우 () 생략 가능
sayHello() { () -> () in
	print("Hello")
}

 

  • 파라미터가 클로저 하나일 경우, 마지막 파라미터이므로 트레일링 클로저 가능
  • closure라는 Argument Label은 트레일링 클로저에서 생략

2. 파라미터가 여러 개인 함수

 

func fetchData(success: () -> (), fail: () -> ()) {
}

// inline Closure
fetchData(success: { () -> () in
	print("Success")
}, fail: { () -> () in
	print("Fail")
})

// Trailing Closure
fetchData(success: { () -> () in
	print("Success")
}) { () -> () in
	print("Fail")
}

클로저 경량 문법

func plus(closure: (Int, Int, Int) -> Int) {
	closure(1, 2, 3)
}

// inline Closure
plus(closure: { (a: Int, b: Int, c: Int) -> Int in
	return a + b + c
})

 

inline Closure 방식을 경량 문법으로 간단하게 바꿔보자 !

 

1. 파라미터 형식과 리턴 형식 생략 가능

plus(closure: (a, b, c) in
	return a + b + c
})

 

2. Parameter Name은 Shortand Argument Names으로 대체하고, 이 경우 Parameter Name과 in 키워드를 삭제

 

Parameter Name : a, b ,c

Shortand Argument Names : $0, $1, $2

 

plus(closure: {
	return $0 + $1 + $2
})

 

3. 단일 리턴문만 남을 경우, return 생략

 

단일 리턴문이란 ?

클로저 내부에 코드가 return 구문 하나만 남은 경우

 

plus(closure: {
	$0 + $1 + $2
})

 

4. 클로저 파라미터가 마지막 파라미터면 트레일링 클로저로 작성

 

plus() {
	$0 + $1 + $2
}

 

5. ()에 값이 아무것도 없다면 생략

 

plus {
	$0 + $1 + $2
}

 

결론적으로 이렇게 간단하게 클로저를 사용할 수 있습니다 !

 


참고

https://babbab2.tistory.com/81?category=828998

 

 

'iOS > Swift' 카테고리의 다른 글

[Swift] stride 함수 / Set  (0) 2022.10.25
[Swift] Swift 알고리즘 - 수학  (0) 2022.10.13
[Swift] Swift 알고리즘 - Dictionary  (0) 2022.10.12
[Swift] Swift 알고리즘 - 문자열 / 배열  (0) 2022.10.11
[Swift] Class vs. Struct vs. Enum  (0) 2022.09.06