특징 | 함수 (Function) | 클로저 (Closure) |
---|---|---|
선언 방법 | func 키워드를 사용하여 선언 | { }를 사용하여 선언 |
이름 유무 | 이름이 반드시 있어야 함 | 이름이 없을 수도 있음 (익명 클로저) |
캡처링 | 함수 내에서는 외부 변수를 캡처하지 않음 | 외부 변수를 캡처할 수 있음 |
반복 사용 | 정의된 함수 이름으로 여러 곳에서 호출 가능 | 필요 시에 바로 사용할 수 있음 (인라인 사용) |
함수 타입 | func로 명시된 타입 | 클로저 타입 (인자 타입) -> (반환 타입) |
인라인 사용 | 인라인 사용 불가능 | 인라인 사용 가능 |
Self 참조 | 클래스 메서드 내에서 self 필요 | 캡처리스트를 통해 self 참조 가능 |
축약된 형태 제공 | 제공되지 않음 | 축약된 형태 제공 (예: 매개변수 및 반환 생략) |
let closure = { () -> () in
print("Closure")
}
let closure = { (name: String) -> String in
return "Hello, \(name)"
}
name = Parameter Name != Argument Label
closure("jjoohee")
closure(name: "jjoohee") //error!
let closure = { () -> String in
return "Hello jjoohee!"
}
closure()
({ () -> () in
print("Hello jjoohee!")
})()
let closure = { () -> () in
print("Closure")
}
기존에 클로저를 대입한 변수나 상수 > 새로운 변수나 상수에 대입할 수도 있음
let closure2 = closure
func doSomething(closure: () -> ()) {
closure()
}
doSomething(closure: { () -> () in
print("Hello!")
})
func doSomething() -> () -> () {
}
func doSomething() -> () -> () {
return { () -> () in
print("Hello jjoohee!")
}
}
let closure = doSomething()
closure()
를 출력하면 Hello jjoohee! 가 나오는것!
함수의 마지막 파라미터가 클로저일 때,
이를 파라미터 값 형식이 아닌 함수 뒤에 붙여 작성하는 문법
이때, Argument Label은 생략된다
중요한 것! 마지막 파라미터가 클로저, Argument Label은 생략!!
func doSomething(closure: () -> ()) {
closure()
}
함수 호출 방법
doSomething(closure: { () -> () in
print("Hello!")
})
func fetchData(success: () -> (), fail: () -> ()) {
//do something...
}
fetchData(success: { () -> () in
print("Success!")
}, fail: { () -> () in
print("Fail!")
})
fetchData(success: { () -> () in
print("Success!")
}) { () -> () in
print("Fail!")
}
파라미터가 여러개일 경우 함수 호출 구문 ()을 마음대로 생략해서는 안됨!!!!
func doSomething(closure: (Int, Int, Int) -> Int) {
closure(1, 2, 3)
}
dosomdthing(closure: { (a: Int, b: Int, c: Int) -> Int in
return a + b+ c
})
dosomething(closure: { (a, b, c) in
return a + b + c
})
dosomething(closure: { (a, b, c) in
return a + b + c
})
a b c 라는 Parameter Name 대신에
a → $0
b → $1
c → $2
$와 index를 이용해 Parameter에 순서대로 접근
doSomething(closure: {
return $0 + $1 + $2
})
doSomething(closure: {
return $0 + $1 + $2
})
doSomething(closure: {
$0 + $1 + $2
})
doSomething() {
$0 + $1 + $2
}
doSomething {
$0 + $1 + $2
}
func doSomething(closure: @autoclosure () -> ()) {
}
doSomething(closure: 1 > 2)
func doSomething(closure: @autoclosure () -> ()) {
closure()
}
원래, 일반 구문은 작성되자마자 실행되어야 하는 것이 맞음
근데 autoclosure로 작성하면, 함수 내에서 클로저를 실행할 때까지 구문이 실행되지 않음
왜냐? 함수가 실행될 시점에 구문을 클로저로 만들어주니까
예시!
let closure: () -> String = {
return "Hello, World!"
}
print(closure()) // "Hello, World!" 출력
func printMessage(_ messageProvider: @autoclosure () -> String) {
print(messageProvider())
}
printMessage("Hello, World!") // "Hello, World!" 출력
func doSomething(closure: () -> ()) {
}
상수에 클로저 대입시 non-escaping Closure 에러가 뜸
func dosomething(closure: () -> ()) {
let f: () -> () = closure
} // Error "non-escaping Closure"
func doSomething(closure: @escaping () -> ()) {
let f: () -> () = closure
}
중첩함수 내부에서 매개변수로 받은 클로저를 사용할 경우 중첩함수를 리턴할 수 없다는 에러가 뜸
func outer(closure: () -> ()) -> () -> () {
func inner() {
closure()
}
return inner
} //중첩함수를 리턴할 수 없다는 에러가 뜸
func outer(closure: @escaping () -> ()) -> () -> () {
func inner() {
closure()
}
return inner
}
만약 함수가 종료된 후 클로저를 실행하는데, 이때 클로저가 함수 내부 값을 사용함
그럼 이때 함수는 이미 종료 되었는데, 클로저는 함수 내부 값을 어떻게 사용할까?
특강 정리하신건가요?! 정리가 너무 깔끔해서 종종 참고하러 오겠습니당