๐ก ํด๋ก์ ๋? ์ด๋ฆ์๋ ํจ์๋ผ๊ณ ์๊ฐํ๋ฉด๋๋ค! ํจ์์ ์์ ํ ๊ธฐ๋ฅ์ด ๋์ผํ๋ฉฐ, ํํ๋ง ๋ค๋ฅด๋ค.
- ์ค์ํํธ๋ ํจ์๋ฅผ ์ผ๊ธ๊ฐ์ฒด๋ก ์ทจ๊ธโ ํจ์๋ ํ์ ์ด๋ผ๋ ๋ป์ด๋ค.
// ํจ์์ ํ์
ํ๊ธฐ๋ฒ
let functionA: (String) -> (String)
let functionB: (Int) -> ()- ํด๋ก์ ์ ๊ธฐ๋ณธํํ
// ํจ์
func aFunction(str: String) -> String {
return "Hello, \(str)"
}
// ๊ฐ์ ๊ธฐ๋ฅ์ผ๋ก, ํด๋ก์ ์ผ๋
let _ = {(str: String) -> String in
return "Hello, \(str)"
}
// ํจ์์ฒ๋ผ ์๋ณด์ด์ง๋ง ํด๋ก์ ์ด๋ค.
let aClosureType = { print("์๋
") }
aClosureType() // ์๋
์ค๊ดํธ๋ ํด๋ก์ (ํจ์)์ด๋ค ๋ผ๋ ์๊ฐ์ ์ ํ์ด ํ์ํ๋ค.
- ๋ณ์์ ํจ์(ํด๋ก์ ) ๋ด๊ธฐ
func aFunction1(_ param: String) -> String {
return param + "!"
}
var a: (String) -> String = aFunction1
a("์๋
") // ์๋
!ํจ์๋ ์ผ๊ธ๊ฐ์ฒด์ด๊ธฐ ๋๋ฌธ์ ๋ณ์์ ํ ๋น์ด ๊ฐ๋ฅํ๋ค.
- ๊ฐ์ฅ ๋ง์ด ์ฌ์ฉํ๋ ํํ
let aClosure1 = { (str: String) in
return "Hello, \(str)"
}
let aClosure2 = { param in
return param + "!"
}์ ์ฝ๋๋ฅผ ๋ณด๋ฉด ๋ฆฌํดํ์ ๋ํ ํ๊ธฐ, ํ๋ผ๋ฏธํฐ ํ์ ์๋ต์ด ๊ฐ๋ฅํ๋ค.
- ํด๋ก์ ๋ฅผ ํ๋ผ๋ฏธํฐ๋ก ๋ฐ์ ๊ฒฝ์ฐ โ ํด๋ก์ ์ ์ฌ์ฉ์ด์
func closureParamFunction(closure: () -> ()) {
print("ํ๋ฆฐํธ ์์")
closure()
}
// ์ผ๋ฐ์ ์ผ๋ก ํด๋ก์ ๋ฅผ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ
closureParamFunction(closure: {
print("ํ๋ฆฐํธ ์ข
๋ฃ")
})์ด๋ ๊ฒ ๋ฐ๋ก ๋ณ์์ ๋ด์ง ์์๋ ๋งค๊ฐ๋ณ์์ ๋ฐ๋ก ํด๋ก์ ๋ฅผ ์ ์ํ์ฌ ์ ๋ฌํ ์ ์๋ค. ์ด๋, ํจ์๋ฅผ ์คํํ ๋ ํ๋ผ๋ฏธํฐ๋ก ์ ๋ฌํ๋ ํจ์๋ฅผ Callbackํจ์๋ผ๊ณ ํ๋ค.
- ํํ ํด๋ก์ ๋ฌธ๋ฒ(trailing closure)
func closureParamFunction(closure: () -> ()) {
print("ํ๋ฆฐํธ ์์")
closure()
}
closureParamFunction {
print("ํ๋ฆฐํธ ์ข
๋ฃ")
}์๊ดํธ๋ฅผ ์์ ์๋ตํด๋ฒ๋ฆด ์ ์๋ค.
- ํํ ํด๋ก์ ์์ ํจ์ ์ด์ธ์ ๋งค๊ฐ๋ณ์๋ ๋ฐ๋ ๊ฒฝ์ฐ
func closureCaseFunction(a: Int, b: Int, closure: (Int) -> Void) {
let c = a + b
closure(c)
}
closureCaseFunction(a: 5, b: 2) { number in
print("์ถ๋ ฅํ ๊น์? \(number)")
}- ์๊ท๋จผํธ ์ด๋ฆ ์ถ์ฝ
func performClosure(param: (String) -> Int) {
pram("Swift")
}
performClosure { $0.count }- Timer์ scheduledTimer๋ฅผ ์ฌ์ฉํ๋ฉด ๋ฐ๋ณต์ ์ผ๋ก ํน์ ํด๋ก์ ๋ฅผ ๋ฐ๋ณตํ ์ ์๋ค.
// repeats๋ฅผ true๋ก ํ๋ฉด 1์ด๋ง๋ค ๋ฐ๋ณตํจ
Timer.scheduledTimer(withTimeInterval: 1, repeats: false) { t in
print("1์ด๋ค ์ถ๋ ฅํ๊ธฐ")
}- ๋ฉํฐํ ํธ๋ ์ผ๋ง ํด๋ก์
func multipleclosure(first: () -> (), second: () -> (), third: () -> ()) {
first()
second()
third()
}
multipleClosure {
// code
} second: {
// code
} third: {
// code
}- ํ๋ก์ ํธ์์ ๋ง์ด ์ฌ์ฉํ๋ ๋ฐฉ์
let emailTextField: UITextField = {
let tf = UITextField()
tf.placeholder = "Email"
tf.backgroundColor = UIColor(...)
tf.font = UIFont.systemFont(ofSize: 14)
return tf
}()@escapingํค์๋ โ ํด๋ก์ ๋ฅผ ์ ๊ฑฐํ์ง ์๊ณ ํจ์์์ ํ์ถ ์ํค๊ฒํด์ฃผ๋ ํค์๋
var aSavedFunction: () -> () = { print("์ถ๋ ฅ") }
func perfomrEscaping(closure: @escaping: () -> ()) {
aSavedFunction = closure
}
performEscaping2(closure: { print("๋ค๋ฅด๊ฒ ์ถ๋ ฅ") })
aSavedFunction() // print("๋ค๋ฅด๊ฒ ์ถ๋ ฅ")@escapingํค์๋๋ฅผ ์ฌ์ฉํจ์ผ๋ก์จ ํ ์์ญ์ ์ ์ฅํด์ ๋ ์ค๋ ์ ์งํ ์ ์๋ค.
@autoclosureํค์๋ โ ์๋์ผ๋ก ํด๋ก์ ๋ฅผ ๋ง๋ค์ด์ฃผ๋ ํค์๋
func someFunction(closure: @autoclosure () -> Bool) {
if closure() {
print("์ฐธ์
๋๋ค.")
} else {
print("๊ฑฐ์ง์
๋๋ค.")
}
}
var num = 1
// ์๋ ์์ฑ์ someFunction(closure: Bool)๋ก ๋ธ
someFunction(closure: { true })์ผ๋ฐ์ ์ผ๋ก ํด๋ก์ ํํ๋ก ์จ๋ ๋์ง๋ง, ๋๋ฌด ๋ฒ๊ฑฐ๋ก์ธ ๋ ์ฌ์ฉํ๋ค. ๋ฒ๊ฑฐ๋ก์์ ํด๊ฒฐํ ์ ์์ง๋ง ์ค์ ์ฝ๋๊ฐ ๋ช ํํด ๋ณด์ด์ง ์์ ์ ์์ผ๋ฏ๋ก ์ฌ์ฉ์ ์ง์ํด์ผ ํ๋ค.
๐ก ์บก์ฒํ์ ํด๋ก์ ๋ ํ์ ์์ญ์ ์กด์ฌํด์ผํ๊ณ , ํด๋ก์ ๋ด๋ถ์์ ์ธ๋ถ์ ์กด์ฌํ๋ ๋ณ์๋ฅผ ๊ณ์ ์ฌ์ฉํด์ผํ๊ธฐ ๋๋ฌธ์ ์์ ์ด ์ฐธ์กฐํ๋ ์ธ๋ถ ๋ณ์๋ฅผ ์บก์ฒํ๋ ํ์์ด๋ค.
- ์บก์ฒ ํ์
func calculate() -> ((Int) -> Int) {
var sum = 0
func square(num: Int) -> Int {
sum += (num * num)
return sum
}
return square
}
// ํจ์๋ฅผ ๋ณ์์ ํ ๋นํ๋ ์๊ฐ ํด๋ก์ ์ ๋๊ฐ์ด ๋์ํ๋ค.
var squareFunc = calculateFunc()
squareFunc(10) // 100
squareFunc(20) // 500
squareFunc(30) // 1400
// ๋ณ์ sum์ด ์บก์ณํ์์ผ๋ก ๋์ ๋จ- ๊ฐ ํ์ ์บก์ฒ์ ์บก์ฒ ๋ฆฌ์คํธ
var num = 1
let valueCaptureClosure = {
print("๋ฒจ๋ฅ๊ฐ ์ถ๋ ฅ: \(num)")
}
num = 7
valueCaptureclosure() // ๋ฒจ๋ฅ๊ฐ ์ถ๋ ฅ: 7
num = 1
let valueCaptureListClosure = { [num] in
print("๋ฒจ๋ฅ๊ฐ ์ถ๋ ฅ(์บก์ฒ๋ฆฌ์คํธ): \(num)")
}
num = 7
valueCaptureListClosure() // ๋ฒจ๋ฅ๊ฐ ์ถ๋ ฅ(์บก์ฒ๋ฆฌ์คํธ): 1ํด๋ก์ ๋ ์์ ์ด ์ฌ์ฉํ ์ธ๋ถ์ ๋ณ์๋ฅผ ์บก์ณํ๋ค. ๋ฐ๋ผ์ ๋ฒจ๋ฅํ์ ์ ๋ฉ๋ชจ๋ฆฌ ์ฃผ์๋ฅผ ์บก์ฒํ์ฌ 7์ด ๋์ค๋ ๊ฒ์ ๋ณผ ์ ์๋ค. ํ์ง๋ง ์บก์ฒ ๋ฆฌ์คํธ๋ฅผ ์ฌ์ฉํ๋ฉด ๊ฐ์ ๋ณต์ฌํด์ ๋ด๊ธฐ ๋๋ฌธ์
- ์ฐธ์กฐ ํ์ ์บก์ฒ์ ์บก์ฒ ๋ฆฌ์คํธ
class SomeClass {
var num = 0
}
var x = SomeClass()
var y = SomeClass()
// x.num = 0, y.num = 0
let refTypeCapture = { [x] in
print(x.num, y.num)
}
x.num = 1
y.num = 1
refTypeCapture() // x.num = 1, y.num = 1์ ์ฝ๋๋ฅผ ๋ณด๋ฉด ์บก์ฒ๋ฆฌ์คํธ์์ x๋ ์ง์ ์ฐธ์กฐ, y๋ ๋ณ์๋ฅผ ์บก์ณํด์ y ๋ณ์๋ฅผ ๊ฐ๋ฅดํค๋ ๊ฒ์ ๋ณผ ์ ์๋ค. ๊ฒฐ๊ตญ ๊ฑฐ์ณ์ ์ฐธ์กฐํ๋ ์๋๋ฉด ์ง์ ์ฐธ์กฐํ๋์ ์ฐจ์ด์ด๊ธฐ ๋๋ฌธ์ ๋๋ค 1๋ก ๋ฐ๋๋ ๊ฒ์ ๋ณผ ์ ์๋ค.
- ์ผ๋ฐ์ ์ธ ํด๋ก์ ์ ์ฌ์ฉ
class Dog {
var name = "์ด์ฝ"
func doSomething() {
// ๋น๋๊ธฐ ์คํ ํด๋ก์ ==> ๋ณ์๋ฅผ ์ค๋ซ๋์ ์ ์ฅํ ํ์๊ฐ ์์
DispatchQueue.global().async { [self] in
print("๋์ ์ด๋ฆ์ \(name)์
๋๋ค.") // ๋๋ self.name
}
}
func doSomething1() {
// ์ฝํ ์ฐธ์กฐ๋ก RC๊ฐ ์ฌ๋ผ๊ฐ์ง ์์
DispatchQueue.global().async { [weak self] in
print("๋์ ์ด๋ฆ์ \(self?.name)์
๋๋ค.")
}
}
func doSomething2() {
//
DispatchQueue.global().async { [weak self] in
guard let weakSelf = self else { return }
print("๋์ ์ด๋ฆ์ \(weakSelf.name)์
๋๋ค.")
}
}
}
var choco = Dog()
choco.doSomething()