클로저
- 스위프트는 함수를 “일급객체”로 취급
- 함수는 타입이다.
- “함수”를 변수에 할당할 수 있음
- 함수를 호출할때, “함수”를 파라미터로 전달할 수 있음
- 함수에서 “함수”를 반환할 수 있음
- 기존의 함수의 형태와 클로저의 형태 비교
// 함수 정의
func aFunction(str: String) -> String {
return "Hello, \(str)"
}
// 클로저의 형태
let _ = {(str: String) -> String in
return "Hello, \(str)"
}
// 클로저의 형태 (타입 추론이 가능한 경우)
// 타입이 결정된 거고 변수에 이를 할당하는 것
let _: (Int, Int) -> Int = {(a, b) in
let result = a + b
return result
}
- 생각의 전환 → 중괄호는 클로저(함수)
// 변수에 담아서 호출하는 것도 가능
let aClosureType = { () -> () in
print("안녕")
}
// () -> () 생략 가능
// let aClousureType = { print("안녕") }
// 실행
aClosureType()
클로저의 형태
- 함수의 형태에서 클로저의 형태로 변형시키기
func add(a: Int, b: Int) -> INt {
let result = a + b
return result
}
// 1단계 이름 없애기
// (a: Int, b: Int) -> Int {
// let result = a + b
// return result
// }
// 2단계 괄호 위치 변경
{ (a: Int, b: Int) -> Int
let result = a + b
return result
}
// 3단계 문법
{ (a: Int, b: Int) -> Int in
let result = a + b
return result
}
// 4단계 타입 생략
{ (a: Int, b: Int) in
let result = a + b
return result
}
// 5단계 타입 생략
{ (a, b) in
let result = a + b
return result
}
- [리턴형에 대한 표기를 생략 가능]

let aClosure1 = { (str: String) -> String in
return "Hello, \(str)"
}
// String이 생략
// 생략되어도 return형이 문자열 형태인 것을 컴파일러가 추론 가능
let aClosureType1 = { (str: String) -> in
return "Hello, \(str)"
}
// 아규먼트 레이블을 따로 사용하지 않음
let aClosure2: (String) -> String = { (str) in
return "Hello, \(str)"
}
let aClosure3 = {
print("This is a closure.")
}
- 파라미터의 타입의 생략도 대부분 가능

// 컴파일러가 타입 추론 가능한 경우 생략 가능
let closureType4: (String) -> String = { str in
return str + "!"
}
let closureType5 = { str in
return str + "!"
}
var a = closureType5
a("hello")
클로저를 사용하는 이유
- 클로저
- 이름이 없는 (익명) 함수
- 왜 이름이 필요없을까?
- 함수를 실행할때 전달하는 형태로 사용하기 때문에 이름이 필요없음

💡 **콜백함수 : 함수를 실행할때 파라미터로 전달하는 함수, 호출하는 함수의 결과를 받아 콜백함수를 다시 실행**
// 1) (클로저를 파라미터로 받는 함수)정의
func closureParamFunction(**closure: () -> ()**) {
print("프린트 시작")
**closure()**
}
func printSwiftFunction() {
print("프린트 종료")
}
func printSwift = { () -> () in
print("swift")
}
// 함수를 파라미터로 넣으면서 실행
closureParamFunction(closure: printSwiftFunction)
closureParamFunction(closure: printSwift)
// 함수를 실행할대 클로저 형태로 전달
// > 본래 정의된 함수를 실행시키면서, 클로저를 사후적으로 정의 가능
// >> 활용도가 늘어남
closureParamFunction(closure: { () -> () in
print("프린트 종료")
}
// () -> () in 생략
closureParamFunction(closure: {
print("프린트 종료 - 1")
print("프린트 종료 - 2")
}
- 2번째 이유


- 즉, 개발자가 향후, 원하는대로 정의할 수 있기 때문에 활용도가 늘어남
// 1) 클로저를 파라미터로 받는 함수 정의
func closureCaseFunction(a: Int, b: Int, closure: (Int) -> Void) {
let c = a + b
closure(c)
}
// 2) 함수를 실행할 때 (클로저 형태로 전달)
// ⭐️ 사후적 정의 가능 ⭐️
closureCaseFunction(a: 5, b: 2, closure: { (n) in
print("이제 출력할께요: \(n)")
}
closureCaseFunction(a: 5, b: 2) {(number) in
print("출력할까요? \(number)")
}
closureCaseFunction(a: 5, b: 3) { (number) in
print("ㅋㅋ")
print("값: \(nuber)")
}
closureCaseFunction(a: 1, b: 2, closure: { number in
for _ in 1...number {
print("ㅋㅋ")
}
})
클로저의 문법 최적화
- 클로저는 실제 사용시 읽기 쉽고 간결한 콛 작성을 위해 축약된 형태의 문법을 제공
[문법 최적화(간소화)]
- 문맥상에서 파라미터와 리턴밸류 타입 추론(Type Inference)
- 싱글 익스프레션인 경우(한줄), 리턴을 안 적어도 됨(Implicit Return)
- 아규먼트 이름을 축약(Shorthand Arguments) >> $0, $1
- 트레일링 클로저 문법 : 함수의 마지막 전달 인자(아규먼트)로 클로저 전달되는 경우, 소괄호를 생략 가능
[트레일링 클로저]

// 1) 클로저를 파라미터로 받는 함수 정의
func closureParamFunction(closure: () -> Void) {
print("프린트 시작")
closure()
}
// 2) 함수를 실행할때 클로저 형태로 전달
// 함수의 마지막 전달 인자(아규먼트)로 클로저 전달되는 경우, 소괄호를 생략 가능
closureParamFunction(closure: {
print("프린트 종료")
})
// 소괄호를 앞으로 가져오기
closureParamFunction(closure: ) {
print("프린트 종료")
}
// 아규먼트 생략 가능
closureParamFunction() {
print("프린트 종료")
}
// 소괄호를 아예 생략할 수도 있음.
// 아래 형태가 함수를 실행하고 마지막 아규먼트로 클로저를 전달했다는 형태에 익숙해져야
closureParamFunction {
print("프린트 종료")
}
- E.g
func closureCaseFunction(a: Int, b: Int, closure: (Int) -> Void) {
let c = a + b
closure(c)
}
// 함수 실행할때 클로저 형태로 전달
closureCaseFunction(a: 3, b: 4) { (number) -> Void in
print("출력할까? \(number)")
}
[파라미터 및 생략 등의 간소화]

func performClosure(param: (String) -> Int) {
param("Swift")
}
// 문법을 최적화하는 과정
// 1) 타입 추론(Type Inference)
performClosure(param: { (str: String) in
return str.count
})
performClosure(param: { str in
return str.count
})
// 아규먼트 이름을 축약 (Shorthand Arguments)
performClosure(param: {
$0.count
})
// 트레일링 클로저
performClosure(param: {
$0.count
})
performClosure() {
$0.count
}
performClosure { $0.count }
- 활용
let closureType1 = { (param) in
return param % 2 == 0
}
let closureType2 = { $0 % 2 == 0 }
let closureType3 = { (a: Int, b:Int) -> Int in
return a * b
}
let closureType4: (Int, Int) -> Int = { (a, b) in
return a * b
}
let closureType5: (Int, Int) -> Int = { $0 * $1 }
사용 예시
Timer.scheduledTimer(withTimeInterval: 0.2, repeats: false, block: <#T##(Timer) -> Void#>)
Timer.scheduledTimer(withTimeInterval: 0.5, repeats: false) { (timer) in
print("0.5초뒤에 출력하기")
}
// 2nd
class ViewController: UIViewController {
}
let vc = ViewController()
//vc.dismiss(animated: true, completion: <#T##(() -> Void)?##(() -> Void)?##() -> Void#>)
vc.dismiss(animated: true) {
print("화면을 닫는 것을 완료했습니다.")
}
- 콜백 함수 파라미터 이름을 completion이라고 짓는 경우가 많음
- 동작이 완료되고 나서 실행될 무언가를 의미함
- 주로 함수가 실행된 결과는 콜백 함수로 전달받아 처리하기 때문에
멀티플 트레일링 클로저
func multipleClosure(first: () -> (), second: () -> (), third: () -> ()) {
first()
second()
third()
}
// 사용 시
multipleClosure {
print("multi-1")
} second: {
print("multi-2")
} third: {
print("multi-3")
}
// 아규먼트 레이블 생략 경우
func multipleClosure2(first: () -> (), _ second: () -> (), third: () -> ()) {
first()
second()
third()
}
// 아규먼트 레이블 생략하지 못함
multipleClosure2 {
print("1")
} _: {
print("2")
} third: {
print("3")
}
반응형
'iOS > Swift' 카테고리의 다른 글
Swift No.25 (0) | 2024.02.03 |
---|---|
Swift No.24 (0) | 2024.02.02 |
Swift No.22 (0) | 2024.01.30 |
Swift No.21 (1) | 2024.01.28 |
Swift No.20 (1) | 2024.01.27 |
클로저
- 스위프트는 함수를 “일급객체”로 취급
- 함수는 타입이다.
- “함수”를 변수에 할당할 수 있음
- 함수를 호출할때, “함수”를 파라미터로 전달할 수 있음
- 함수에서 “함수”를 반환할 수 있음
- 기존의 함수의 형태와 클로저의 형태 비교
// 함수 정의
func aFunction(str: String) -> String {
return "Hello, \(str)"
}
// 클로저의 형태
let _ = {(str: String) -> String in
return "Hello, \(str)"
}
// 클로저의 형태 (타입 추론이 가능한 경우)
// 타입이 결정된 거고 변수에 이를 할당하는 것
let _: (Int, Int) -> Int = {(a, b) in
let result = a + b
return result
}
- 생각의 전환 → 중괄호는 클로저(함수)
// 변수에 담아서 호출하는 것도 가능
let aClosureType = { () -> () in
print("안녕")
}
// () -> () 생략 가능
// let aClousureType = { print("안녕") }
// 실행
aClosureType()
클로저의 형태
- 함수의 형태에서 클로저의 형태로 변형시키기
func add(a: Int, b: Int) -> INt {
let result = a + b
return result
}
// 1단계 이름 없애기
// (a: Int, b: Int) -> Int {
// let result = a + b
// return result
// }
// 2단계 괄호 위치 변경
{ (a: Int, b: Int) -> Int
let result = a + b
return result
}
// 3단계 문법
{ (a: Int, b: Int) -> Int in
let result = a + b
return result
}
// 4단계 타입 생략
{ (a: Int, b: Int) in
let result = a + b
return result
}
// 5단계 타입 생략
{ (a, b) in
let result = a + b
return result
}
- [리턴형에 대한 표기를 생략 가능]

let aClosure1 = { (str: String) -> String in
return "Hello, \(str)"
}
// String이 생략
// 생략되어도 return형이 문자열 형태인 것을 컴파일러가 추론 가능
let aClosureType1 = { (str: String) -> in
return "Hello, \(str)"
}
// 아규먼트 레이블을 따로 사용하지 않음
let aClosure2: (String) -> String = { (str) in
return "Hello, \(str)"
}
let aClosure3 = {
print("This is a closure.")
}
- 파라미터의 타입의 생략도 대부분 가능

// 컴파일러가 타입 추론 가능한 경우 생략 가능
let closureType4: (String) -> String = { str in
return str + "!"
}
let closureType5 = { str in
return str + "!"
}
var a = closureType5
a("hello")
클로저를 사용하는 이유
- 클로저
- 이름이 없는 (익명) 함수
- 왜 이름이 필요없을까?
- 함수를 실행할때 전달하는 형태로 사용하기 때문에 이름이 필요없음

💡 **콜백함수 : 함수를 실행할때 파라미터로 전달하는 함수, 호출하는 함수의 결과를 받아 콜백함수를 다시 실행**
// 1) (클로저를 파라미터로 받는 함수)정의
func closureParamFunction(**closure: () -> ()**) {
print("프린트 시작")
**closure()**
}
func printSwiftFunction() {
print("프린트 종료")
}
func printSwift = { () -> () in
print("swift")
}
// 함수를 파라미터로 넣으면서 실행
closureParamFunction(closure: printSwiftFunction)
closureParamFunction(closure: printSwift)
// 함수를 실행할대 클로저 형태로 전달
// > 본래 정의된 함수를 실행시키면서, 클로저를 사후적으로 정의 가능
// >> 활용도가 늘어남
closureParamFunction(closure: { () -> () in
print("프린트 종료")
}
// () -> () in 생략
closureParamFunction(closure: {
print("프린트 종료 - 1")
print("프린트 종료 - 2")
}
- 2번째 이유


- 즉, 개발자가 향후, 원하는대로 정의할 수 있기 때문에 활용도가 늘어남
// 1) 클로저를 파라미터로 받는 함수 정의
func closureCaseFunction(a: Int, b: Int, closure: (Int) -> Void) {
let c = a + b
closure(c)
}
// 2) 함수를 실행할 때 (클로저 형태로 전달)
// ⭐️ 사후적 정의 가능 ⭐️
closureCaseFunction(a: 5, b: 2, closure: { (n) in
print("이제 출력할께요: \(n)")
}
closureCaseFunction(a: 5, b: 2) {(number) in
print("출력할까요? \(number)")
}
closureCaseFunction(a: 5, b: 3) { (number) in
print("ㅋㅋ")
print("값: \(nuber)")
}
closureCaseFunction(a: 1, b: 2, closure: { number in
for _ in 1...number {
print("ㅋㅋ")
}
})
클로저의 문법 최적화
- 클로저는 실제 사용시 읽기 쉽고 간결한 콛 작성을 위해 축약된 형태의 문법을 제공
[문법 최적화(간소화)]
- 문맥상에서 파라미터와 리턴밸류 타입 추론(Type Inference)
- 싱글 익스프레션인 경우(한줄), 리턴을 안 적어도 됨(Implicit Return)
- 아규먼트 이름을 축약(Shorthand Arguments) >> $0, $1
- 트레일링 클로저 문법 : 함수의 마지막 전달 인자(아규먼트)로 클로저 전달되는 경우, 소괄호를 생략 가능
[트레일링 클로저]

// 1) 클로저를 파라미터로 받는 함수 정의
func closureParamFunction(closure: () -> Void) {
print("프린트 시작")
closure()
}
// 2) 함수를 실행할때 클로저 형태로 전달
// 함수의 마지막 전달 인자(아규먼트)로 클로저 전달되는 경우, 소괄호를 생략 가능
closureParamFunction(closure: {
print("프린트 종료")
})
// 소괄호를 앞으로 가져오기
closureParamFunction(closure: ) {
print("프린트 종료")
}
// 아규먼트 생략 가능
closureParamFunction() {
print("프린트 종료")
}
// 소괄호를 아예 생략할 수도 있음.
// 아래 형태가 함수를 실행하고 마지막 아규먼트로 클로저를 전달했다는 형태에 익숙해져야
closureParamFunction {
print("프린트 종료")
}
- E.g
func closureCaseFunction(a: Int, b: Int, closure: (Int) -> Void) {
let c = a + b
closure(c)
}
// 함수 실행할때 클로저 형태로 전달
closureCaseFunction(a: 3, b: 4) { (number) -> Void in
print("출력할까? \(number)")
}
[파라미터 및 생략 등의 간소화]

func performClosure(param: (String) -> Int) {
param("Swift")
}
// 문법을 최적화하는 과정
// 1) 타입 추론(Type Inference)
performClosure(param: { (str: String) in
return str.count
})
performClosure(param: { str in
return str.count
})
// 아규먼트 이름을 축약 (Shorthand Arguments)
performClosure(param: {
$0.count
})
// 트레일링 클로저
performClosure(param: {
$0.count
})
performClosure() {
$0.count
}
performClosure { $0.count }
- 활용
let closureType1 = { (param) in
return param % 2 == 0
}
let closureType2 = { $0 % 2 == 0 }
let closureType3 = { (a: Int, b:Int) -> Int in
return a * b
}
let closureType4: (Int, Int) -> Int = { (a, b) in
return a * b
}
let closureType5: (Int, Int) -> Int = { $0 * $1 }
사용 예시
Timer.scheduledTimer(withTimeInterval: 0.2, repeats: false, block: <#T##(Timer) -> Void#>)
Timer.scheduledTimer(withTimeInterval: 0.5, repeats: false) { (timer) in
print("0.5초뒤에 출력하기")
}
// 2nd
class ViewController: UIViewController {
}
let vc = ViewController()
//vc.dismiss(animated: true, completion: <#T##(() -> Void)?##(() -> Void)?##() -> Void#>)
vc.dismiss(animated: true) {
print("화면을 닫는 것을 완료했습니다.")
}
- 콜백 함수 파라미터 이름을 completion이라고 짓는 경우가 많음
- 동작이 완료되고 나서 실행될 무언가를 의미함
- 주로 함수가 실행된 결과는 콜백 함수로 전달받아 처리하기 때문에
멀티플 트레일링 클로저
func multipleClosure(first: () -> (), second: () -> (), third: () -> ()) {
first()
second()
third()
}
// 사용 시
multipleClosure {
print("multi-1")
} second: {
print("multi-2")
} third: {
print("multi-3")
}
// 아규먼트 레이블 생략 경우
func multipleClosure2(first: () -> (), _ second: () -> (), third: () -> ()) {
first()
second()
third()
}
// 아규먼트 레이블 생략하지 못함
multipleClosure2 {
print("1")
} _: {
print("2")
} third: {
print("3")
}
반응형
'iOS > Swift' 카테고리의 다른 글
Swift No.25 (0) | 2024.02.03 |
---|---|
Swift No.24 (0) | 2024.02.02 |
Swift No.22 (0) | 2024.01.30 |
Swift No.21 (1) | 2024.01.28 |
Swift No.20 (1) | 2024.01.27 |