์๋ ํ์ธ์~
์ค๋์ ๊ธฐ์กด์ ์์ฑํ๋ ํด๋ก์ ํฌ์คํ ์ด
์ข ์ด์คํ ๋๋์ด ๋ค์ด ๋ค์ ํ๋์ ํฌ์คํ ์ผ๋ก ์ ๋ฆฌํด๋ณด๋ ค๊ณ ํฉ๋๋ค.
Closure๋?
Closure๋ Swift์์ ์ด๋ฆ์ด ์๋ ์ต๋ช ํจ์์ ๋๋ค.
ํจ์์ ๋ง์ฐฌ๊ฐ์ง๋ก, ์ ๋ ฅ๊ฐ์ ๋ฐ์ ์ถ๋ ฅ๊ฐ์ ๋ฐํํ ์ ์์ต๋๋ค.
Swift์์๋ closure๊ฐ ์ผ๊ธ ๊ฐ์ฒด๋ก ์ทจ๊ธ๋์ด, ๋ณ์๋ ์์์ ์ ์ฅํ๊ฑฐ๋ ํจ์์ ์ธ์๋ก ์ ๋ฌํ ์ ์์ต๋๋ค.
๋ํ closure๋ ์ค์ฒฉ๋ ์ ์์ผ๋ฉฐ, ์ด๋ฅผ ํตํด ๋ ๋ณต์กํ ๊ธฐ๋ฅ์ ๊ตฌํํ ์ ์์ต๋๋ค.
Closure์ ํํ ๋ฐฉ๋ฒ
Swift์์๋ ๋ค์๊ณผ ๊ฐ์ ํ์์ผ๋ก closure๋ฅผ ํํํ ์ ์์ต๋๋ค.
{ (parameters) -> ReturnType in
statements
}
์๋ฅผ ๋ค์ด, map ๋ฉ์๋๋ฅผ ์ฌ์ฉํ closure์ ์์๋ฅผ ์ดํด๋ณด๋ฉด ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
let numbers = [1, 2, 3, 4, 5]
let mappedNumbers = numbers.map({ (number: Int) -> Int in
return number * 2
})
print(mappedNumbers) // [2, 4, 6, 8, 10]
์ ์ฝ๋์์, map ๋ฉ์๋๋ ํด๋ก์ ๋ฅผ ์ธ์๋ก ๋ฐ์ต๋๋ค.
ํด๋ก์ ๋ number๋ผ๋ Int ํ์ ์ ์ธ์๋ฅผ ๋ฐ์, number * 2๋ฅผ ๋ฐํํฉ๋๋ค.
1๊ธ ๊ฐ์ฒด๋ก์์ Closure
Swift์์๋ closure๊ฐ 1๊ธ ๊ฐ์ฒด๋ก ์ทจ๊ธ๋ฉ๋๋ค.
์ฆ, ๋ค๋ฅธ ๊ฐ์ฒด์ ๋์ผํ ๋ฐฉ์์ผ๋ก ๋ค๋ฃฐ ์ ์๋ค๋ ์๋ฏธ์ ๋๋ค.
closure๋ ๋ณ์๋ ์์์ ์ ์ฅํ ์ ์์ผ๋ฉฐ, ํจ์์ ์ธ์๋ก ์ ๋ฌํ๊ฑฐ๋ ๋ฐํํ ์ ์์ต๋๋ค.
let addClosure: (Int, Int) -> Int = { (a, b) in
return a + b
}
let result = addClosure(1, 2)
print(result) // 3
์ ์ฝ๋์์, addClosure๋ ๋ ๊ฐ์ Int ํ์ ์ธ์๋ฅผ ๋ฐ์ ๋ํ ๊ฐ์ ๋ฐํํ๋ closure์ ๋๋ค.
์ด closure๋ addClosure ์์์ ์ ์ฅ๋ฉ๋๋ค.
Closure์ ์ถ์ฝํํ
Swift์์๋ closure์ ์ถ์ฝํํ๋ฅผ ์ง์ํฉ๋๋ค.
1. ์ถ์ฝํํ ์๋ ํด๋ก์ ํํ์
{ (๋งค๊ฐ๋ณ์: ๋งค๊ฐ๋ณ์ํ์
) -> ๋ฐํํ์
in
// ํด๋ก์ ๊ตฌํ
}
// ์์
let greeting = { (name: String) -> String in
return "Hello, \(name)!"
}
print(greeting("Swift"))
// ์ถ๋ ฅ: "Hello, Swift!"
2. ๋งค๊ฐ๋ณ์ ํ์ ์๋ต
{ (๋งค๊ฐ๋ณ์) -> ๋ฐํํ์
in
// ํด๋ก์ ๊ตฌํ
}
// ์์
let greeting = { name -> String in
return "Hello, \(name)!"
}
print(greeting("Swift"))
// ์ถ๋ ฅ: "Hello, Swift!"
3. ๋งค๊ฐ๋ณ์์ ๋ฐํํ์ ์๋ต
{ ๋งค๊ฐ๋ณ์ in
// ํด๋ก์ ๊ตฌํ
}
// ์์
let greeting = { name in
return "Hello, \(name)!"
}
print(greeting("Swift"))
// ์ถ๋ ฅ: "Hello, Swift!"
4. ์ถ์ฝ ์ธ์ ์ด๋ฆ ์ฌ์ฉ
{ $0 + $1 }
// ์์
let add = { $0 + $1 }
print(add(1, 2))
// ์ถ๋ ฅ: 3
5. ํํ ํด๋ก์
someFunction(argument1, argument2) { ๋งค๊ฐ๋ณ์ in
// ํด๋ก์ ๊ตฌํ
}
// ์์
let numbers = [1, 2, 3]
let mappedNumbers = numbers.map { $0 * 2 }
print(mappedNumbers)
// ์ถ๋ ฅ: [2, 4, 6]
@autoclosure
@autoclosure๋ ์ธ์๋ก ์ ๋ฌ๋๋ ํํ์์ ์๋์ผ๋ก closure๋ก ๋ณํํด ์ฃผ๋ ์ญํ ์ ํฉ๋๋ค.
์ด๋ฅผ ํตํด ์ธ์๋ก ์ ๋ฌ๋ closure๋ฅผ ํ์ํ ๋ ์ฌ์ฉํ ์ ์์ต๋๋ค.
func printResult(_ result: @autoclosure () -> Void) {
print("before closure")
result()
print("after closure")
}
printResult(print("Hello, world!"))
์ ์ฝ๋์์, printResult ํจ์๋ @autoclosure ์์ฑ์ ์ฌ์ฉํ์ฌ
์ธ์๋ก ์ ๋ฌ๋๋ print("Hello, world!") ํจ์๋ฅผ ์๋์ผ๋ก closure๋ก ๋ณํํฉ๋๋ค.
๋ฐ๋ผ์ closure๋ฅผ ํ์ํ ๋ ์ฌ์ฉํ ์ ์์ต๋๋ค.
@escaping
@escaping์ closure๊ฐ ํจ์์ ๋ฒ์๋ฅผ ๋ฒ์ด๋์ ์คํ๋ ๋ ์ฌ์ฉํ๋ ์์ฑ์ ๋๋ค. ์ด ์์ฑ์ closure๋ฅผ escaping closure๋ก ์ ์ํ๋ ์ญํ ์ ํฉ๋๋ค.
func myFunc(closure: @escaping () -> Void) {
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
closure()
}
}
myFunc { print("Hello, world!") }
์ ์ฝ๋์์ myFunc ํจ์๋ @escaping ์์ฑ์ ์ฌ์ฉํ์ฌ closure๋ฅผ escaping closure๋ก ์ ์ํฉ๋๋ค.
์ด๋ ๊ฒ ์ ์๋ closure๋ ํจ์์ ๋ฒ์๋ฅผ ๋ฒ์ด๋์ ์คํํ ์ ์์ต๋๋ค.
myFunc ํจ์ ๋ด๋ถ์์๋ 1์ด ํ์ closure๊ฐ ์คํ๋๊ฒ ๋๋ ๊ฒ์ด์ฃ .
Closure์ ์บก์ฒ์ ์บก์ฒ ๋ฆฌ์คํธ
Closure๋ ํด๋น closure๊ฐ ์ ์ธ๋ ์ฝํ ์คํธ์์ ์ ์๋ ๋ณ์๋ ์์๋ฅผ ์บก์ฒํ ์ ์์ต๋๋ค. ์ด๋ฅผ ํตํด closure๊ฐ ์ ์ธ๋ ์์ ์ ๋ณ์๋ ์์ ๊ฐ์ ์ฌ์ฉํ ์ ์์ต๋๋ค.
func makeIncrementer(forIncrement amount: Int) -> () -> Int {
var runningTotal = 0
func incrementer() -> Int {
runningTotal += amount
return runningTotal
}
return incrementer
}
let incrementByTen = makeIncrementer(forIncrement: 10)
print(incrementByTen()) // 10
print(incrementByTen()) // 20
print(incrementByTen()) // 30
let incrementByFive = makeIncrementer(forIncrement: 5)
print(incrementByFive()) // 5
print(incrementByFive()) // 10
print(incrementByTen()) // 40
์ด ์ฝ๋๋ ์บก์ฒ์ ์บก์ฒ๋ฆฌ์คํธ๋ฅผ ์ค๋ช ํ ๋ ๊ฐ์ฅ ๋ง์ด ์ฌ์ฉ๋๋ ์์๋ผ๊ณ ํด์ ๊ฐ์ ธ์๋ดค์ต๋๋ค.
์ฝ๋๋ฅผ ์ค๋ช ํด ๋ณด์๋ฉด
์ ์ฝ๋์์ makeIncrementer ํจ์๋ closure๋ฅผ ๋ฐํํฉ๋๋ค.
๋ฐํ๋ closure๋ runningTotal ๋ณ์๋ฅผ ์บก์ฒํ์ฌ, amount ๋งํผ ์ฆ๊ฐ์ํค๋ฉฐ ๊ฐ์ ๋ฐํํฉ๋๋ค.
incrementByTen๊ณผ incrementByFive๋
๊ฐ๊ฐ makeIncrementer ํจ์๋ฅผ ํธ์ถํ์ฌ ๋ฐํ๋ closure๋ฅผ ์ ์ฅํฉ๋๋ค.
์ด๋ฅผ ์ด์ฉํ์ฌ ๋ closure๋ ๊ฐ๊ฐ ๋ค๋ฅธ runningTotal ๊ฐ์ ๊ฐ์ง๊ฒ ๋๊ณ ์๋ก ๋ ๋ฆฝ์ ์ผ๋ก ๋์ํ๊ฒ ๋ฉ๋๋ค.
Closure์์๋ ์บก์ณ ๋ฆฌ์คํธ๋ฅผ ์ฌ์ฉํ์ฌ, ์บก์ฒ๋๋ ๋ณ์๋ ์์์ ๋ฒ์๋ฅผ ์ ํํ ์ ์์ต๋๋ค.
์๋ฅผ ๋ค์ด, [weak self]๋ฅผ ์บก์ณ ๋ฆฌ์คํธ๋ก ์ง์ ํ๋ฉด
ํด๋น closure์์ self๋ฅผ ๊ฐํ ์ฐธ์กฐ๊ฐ ์๋ ์ฝํ ์ฐธ์กฐ๋ก ์บก์ฒํ ์ ์์ต๋๋ค.
class MyClass {
var myProperty: String = "Hello"
func myFunc() {
DispatchQueue.main.asyncAfter(deadline: .now() + 1) { [weak self] in
guard let self = self else { return }
print(self.myProperty)
}
}
}
let myObject = MyClass()
myObject.myFunc()
์ฝ๋์ ๋ํด ๊ฐ๋ตํ๊ฒ ์ค๋ช ํด ๋ณด์๋ฉด
์ ์ฝ๋์์ MyClass ํด๋์ค๋ myFunc ๋ฉ์๋ ๋ด๋ถ์์ closure๋ฅผ ์ฌ์ฉํฉ๋๋ค.
์ด closure๋ myProperty ํ๋กํผํฐ๋ฅผ ์บก์ฒํฉ๋๋ค.
myFunc ๋ฉ์๋์์๋ DispatchQueue.main.asyncAfter๋ฅผ ์ฌ์ฉํ์ฌ closure๋ฅผ 1์ด ํ์ ์คํํฉ๋๋ค.
์ด๋, [weak self]๋ฅผ ์บก์ฒ ๋ฆฌ์คํธ๋ก ์ง์ ํ์ฌ self๋ฅผ ์ฝํ ์ฐธ์กฐ๋ก ์บก์ฒํฉ๋๋ค.
๋ฐ๋ผ์, MyClass ์ธ์คํด์ค๊ฐ ํด์ ๋๋ฉด closure๊ฐ ์คํ๋ ๋ self๋ nil์ด ๋ฉ๋๋ค.
์ด๋ฅผ ๋ฐฉ์งํ๊ธฐ ์ํด guard let self = self else { return }๋ฅผ ์ฌ์ฉํ์ฌ self๊ฐ nil์ธ ๊ฒฝ์ฐ์๋
๋ ์ด์ closure๋ฅผ ์คํํ์ง ์๋๋ก ํฉ๋๋ค.
Closure์ ์ข ๋ฅ, ํํ ๋ฐฉ๋ฒ, 1๊ธ ๊ฐ์ฒด๋ก์์ ํน์ง
์ถ์ฝ ํํ, @autoclosure, @escaping, ์บก์ฒ, ์บก์ฒ ๋ฆฌ์คํธ ๋ฑ์ ๋ํด ์ ๋ฆฌํด ๋ดค์ต๋๋ค~
@autoclosure๋ฅผ ์ ์ผํ๊ฒ ์์ง ์ฌ์ฉํด๋ณด์ง ์์๋ ๊ฒ ๊ฐ๋ค์.
ํน์๋ ์ฌ์ฉํ๊ฒ ๋๋ค๋ฉด ์ด ํฌ์คํ ์ ์ถ๊ฐํด ๋ณด๊ฒ ์ต๋๋ค.
๊ทธ๋ผ ์ด๋ง ๐๐ป ๐๐ป ๐๐ป
'iOS > Swift' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[Swift] ์ต์ ๋(Optional)์ ๋ํด์ (0) | 2023.03.17 |
---|---|
[Swift] ์ ๊ทผ์ ์ด์(Access Control)์ ๋ํด์ (0) | 2023.03.15 |
[Swift] Generics์ ๋ํด์ (0) | 2023.03.09 |
[Swift] ARC(Automatic Reference Counting)์ ๋ํด์ ์์๋ณด์. (0) | 2023.03.04 |
[Swift] GCD(Grand Central Dispatch)์ ๋ํด์ (0) | 2023.03.01 |