Swift Closure 이해하기
- Closure는 함수를 변수의 형태로 만든 것이라고 이해하면 쉽다.
- 일반적인 함수 형태와 비교해서 보면 구조가 더 명확하게 보인다.
Normal Function vs Closure
func someFunction(name: String, age: Int) -> String {
print("Normal Function")
return "name: \(name), age: \(age)"
}
let someClosure: (_ name: String, _ age: Int) -> String = { name, age in
print("Closure Form")
return "name: \(name), age: \(age)"
}
- normal function과 마찬가지로, 선언을 위해 이름을 정하고, 매개변수 여부를 정한 후 return type을 정한다.
- closure는 함수의 기능을 하는 변수라고 봤을 때 = 이후에 {} 블록을 이용하여 값을 표기한다.
- closure의 경우 매개변수 앞에 ‘_’를 붙임으로써 매개변수로 들어올 값들의 의미를 명시할 수 있다.
Closure의 축약된 형태
let someClosure: (String) -> Void = {
print("name: \($0)")
return
}
- 매개변수의 의미를 명시하지 않아도 되는 경우는 생략하고 type만으로 사용할 수 있다.
- closure의 경우 매개변수의 값을 그대로 값에서 사용할 수 없기에
name in
과 같은 형태로 값 내에서 사용할 이름을 정해주어야 하는데, 생략하고 싶은 경우 생략하고 매개변수의 순서를 $0
와 같은 형태로 사용할 수도 있다. ($0, $1, $2, .. 매개변수의 순서를 명시한 숫자다.)
- Closure의 예시 뿐만 아니라 지나치게 생략된 코드는 가독성을 심각하게 저하 시킬 수 있으니 주의해서 사용하는 것이 좋다.
매개변수와 반환 여부에 따른 Closure의 형태
- Closure 형태 - 매개변수 x, 반환 x
func someFunction() {
...
}
let someClosure : () -> Void = {
...
}
- Closure 형태 - 매개변수 o, 반환 x
func someFunction(name: String) {
...
}
let someClosure : (_ name: String) -> Void = { name in
...
}
- Closure 형태 - 매개변수 x, 반환 o
func someFunction() -> String {
...
return "someFunction"
}
let someClosure : () -> String = {
...
return "someClosure"
}
- Closure 형태 - 매개변수 o, 반환 o
func someFunction(name: String) {
...
return "name: \(name)"
}
let someClosure : (_ name: String) -> String = { name in
...
return "name: \(name)"
}
Closure의 Void type 명시
let someClosure: () -> Void = {
print("someClosure 입니다")
return
}
let someClosure: () -> () = {
print("someClosure 입니다")
return
}
- 자료형이 Void인 경우 () → () 혹은 () → Void 모두 가능하다.
Closure 사용 예시
func someFunction(name: String, age: Int) -> String {
print("Normal Function")
return "name: \(name), age: \(age)"
}
let someClosure: (_ name: String, _ age: Int) -> String = { name, age in
print("Closure Form")
return "name: \(name), age: \(age)"
}
let value = someFunction(name: "Flamozzi", age: 10)
let result = someClosure("플라모찌", 10)
print(value)
print(result)
Normal Function
Closure Form
name: Flamozzi, age: 10
name: 플라모찌, age: 10
let result = someClosure("플라모찌", 10)
에서 볼 수 있는 것 처럼 closure의 매개변수 값을 정할 때는 name: “플라모찌”
와 같은 형태로 이름을 명시할 수 없다. (바로 값을 입력하면 된다.)
- 따라서 코드 가독성을 위해선
let someClosure: (_ name: String, _ age: Int) -> String
과 같은 형태로 매개변수 앞에 ‘_’을 사용하여 의미 명시를 해주는 것이 좋다.
Closure를 실제 프로젝트에서 사용하는 경우
- 함수가 사용되는 모든 곳에서 사용
- 함수를 만들지 않고, closure의 형태로 만들어서 바로 호출하여 사용하는 경우가 많음
- 이벤트 처리
- 고차함수에서 사용
- 비동기 처리할 때 보통 사용
- 콜렉션의 연산자들에서 사용
고차함수(high order function)에서 Closure를 매개변수로 사용하는 경우
- 함수에서 Closure를 매개변수로 사용하는 경우의 일반적 이해
func saySomething(name: String) {
...
}
saySomething(name: "문자열 값")
func someFunction(completion: () -> Void) {
print(#function)
completion()
}
someFunction(completion: {
print("completion 터트려짐")
})
- 코드에서 딜레이를 주는 예시
func someFunction(completion: @escaping () -> Void) {
print(#function)
DispatchQueue.main.asyncAfter(deadline: .now() + 2, execute: {
completion()
})
}
someFunction(completion: {
print("completion 터트려짐")
})
someFunction({
print("completion 터트려짐")
})
someFunction{
print("completion 터트려짐")
}
someFunction() {
print("completion 터트려짐")
}
- 함수에서 Closure를 매개변수 및 반환 값이 있는 예시
func someFunction(completion: (_ name: String) -> Void) {
print(#function)
completion("호롤롤로")
}
someFunction(completion: { name in
print("completion 터트려짐 name: \(name)")
})
func someFunction(completion: (_ name: String) -> String) {
print(#function)
let result = completion("호롤롤로")
print(#function + "result: \(result)")
}
someFunction(completion: { (name: String) -> String in
return "completion 터트려짐 name: \(name)"
})
someFunction(completion: { name in
return "completion 터트려짐 name: \(name)"
})
고차함수(high order function)에서 반환을 Closure로 하는 경우
- 함수의 반환으로 Closure를 갖는 경우의 일반적 이해
func saySomething() -> String {
return "리턴 스트링"
}
let value : String = satSomething()
func someFunction() -> () -> Void {
return {
print("호호호")
}
}
let result : () -> Void = someFunction()
result()
호호호
- 반환 클로저의 매개변수가 있는 예시
func someFunction() -> (_ name: String) -> Void {
return { (name: String) in
print("안녕하세요! name: \(name)")
}
}
let result : (_ name: String) -> Void = someFunction()
result("Flamozzi")
안녕하세요! name: Flamozzi
- 매개변수 및 반환이 있는 예시
func someFunction() -> (_ name: String) -> String {
return { (name: String) in
return "안녕하세요! name: \(name)"
}
}
let result : (_ name: String) -> String = someFunction()
let finalResult : String = result("Flamozzi")
print(finalResult)
안녕하세요! name: Flamozzi