์ง๋ ์๊ฐ์ ๊ฐ์ธ์ ์ผ๋ก ํด๋ก์ ์ ๋ํด์ ์ข ๋ ์์๋ดค๋๋ฐ ์ค๋ ๊ฐ์์์๋ ํด๋ก์ ์ ๋ํ ์ง๋๋ฅผ ๋๊ฐ๋ค.
๋ณต์ต ์ฐจ์์์ ๊ฐ์๋ฅผ ๋ค์ผ๋ฉด์ ๋ค์ ํ ๋ฒ ์ ๋ฆฌํด๋ดค๋ค.
ํด๋ก์
ํด๋ก์ ๋ ๊ธฐ๋ฅ์ ๊ฐ๊ณ ์๋ ์ฝ๋ ๋ธ๋ก์ด๋ค.
ํด๋ก์ ์์๋ ์์์ ๋ณ์์ ๋ํ ์ฐธ์กฐ๋ฅผ ์บก์ณํ๊ณ ์ ์ฅํ ์ ์์ผ๋ฉฐ ํฌ๊ฒ 3๊ฐ์ง๋ก ๊ตฌ๋ถํ๋ค.
- ์ ์ญ ํจ์
- ์ค์ฒฉ ํจ์
- ํด๋ก์ ํํ์
1. ์ ์ญ ํจ์
์ฒซ ๋ฒ์งธ๋ก ์ ์ญํจ์๋ ์ฐ๋ฆฌ๊ฐ ํ๋ก๊ทธ๋๋ฐ์ ํ๋ฉด์ ์ ์ํ๊ณ ํธ์ถํ๋ ํจ์๋ค์ด๋ค. func ํค์๋๋ฅผ ํตํด ์ ์ํ๋ค. ์ ์ญํจ์๋ ์ด๋ฆ์ ๊ฐ์ง๊ณ ์๊ณ ์ด๋ ํ ๊ฐ๋ ์บก์ณํ์ง ์๋ ํด๋ก์ ์ด๋ค.
func justFunction() -> String {
return "KODO"
}
2. ์ค์ฒฉ ํจ์
๋ ๋ฒ์งธ๋ก ์ค์ฒฉ ํจ์๋ ์ด๋ฆ์ ๊ฐ์ง๊ณ ๋๋ฌ์ผ ํจ์๋ก๋ถํฐ ๊ฐ์ ์บก์ณํ ์ ์๋ ํด๋ก์ ์ด๋ค.
func outerFunction() -> (() -> Int) {
func innerFunction() -> Int {
var num: Int = 1
return num
}
return innerFunction
}
3. ํด๋ก์ ํํ์
in ํค์๋๋ฅผ ๊ธฐ์ค์ผ๋ก ํด๋ก์ ํค๋์ ํด๋ก์ ๋ฐ๋๋ก ๊ตฌ๋ถ๋๋ค.
let closure = { (name: String) -> String in
return "\(name)"
}
ํด๋ก์ ํํ์์ผ๋ก ๋ณํํด๋ณด๊ธฐ
๊ณต์ ๋ฌธ์์ ๋์์๋ ๊ฒ์ฒ๋ผ sorted ๋ฉ์๋๋ฅผ ๊ฐ์ง๊ณ ํด๋ก์ ์ ๋ํด ์์๋ณด๋๋ก ํ์.
[String] ํ์ ์ ๋ฐฐ์ด์ ๋ด๋ฆผ์ฐจ์์ผ๋ก ์ ๋ ฌํ๊ธฐ ์ํด์๋ sorted ๋ฉ์๋์ ๊ฐ์ ๋ํ ๋น๊ต๋ฅผ ํ ์ ์๋ ํจ์๋ฅผ ์ ๋ฌ ์ธ์๋ก ์ ๋ฌํด์ผ ํ๋ค.
let alphabets = ["a", "b", "c", "d", "e"]
func comparedTwoValues(_ s1: String, _ s2: String) -> Bool {
return s1 > s2 // ๋ด๋ฆผ์ฐจ์์ผ๋ก ์ ๋ ฌ
}
let reversed = alphabets.sorted(by: compareTwoValues)
print(reversed)
์ง๊ธ ๊ฐ์ ๊ฒฝ์ฐ๋ ๊ฐ๋จํ๊ฒ ๋ ์๋ฅผ ๋น๊ตํ๋ ์ํฉ์ด๋ผ์ ๊ฐ์ ๋น๊ตํ ์ ์๋ ํจ์๋ฅผ ์ ์ํ๊ณ ์ด๋ฅผ ์ ๋ฌ์ธ์๋ก ๋๊ฒจ์คฌ์ง๋ง ๋งค๋ฒ ํจ์๋ฅผ ์ ์ํ๋ค๋ ๊ฒ์ ๊ฝค๋ ๊ท์ฐฎ์ ๊ฒ์ด๋ค.
์ด๋ฌํ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํด์ฃผ๋ ๊ฒ์ด ๋ฐ๋ก ํด๋ก์ ์ด๋ค.
์ฐ์ ํด๋ก์ ๋ ์๋์ ๊ฐ์ ํํ๋ฅผ ๋๋ฉฐ, in ํค์๋๋ฅผ ๊ธฐ์ค์ผ๋ก ํด๋ก์ ํค๋์ ํด๋ก์ ๋ฐ๋๋ก ๋๋๋ค.
{ (ํ๋ผ๋ฏธํฐ) -> ๋ฐํ ํ์
in
์คํ ์ฝ๋
}
์ฐ์ ์์ ์ฝ๋๋ฅผ ํด๋ก์ ๋ก ๋ณํํด๋ณด๋ฉด ์๋์ ๊ฐ๋ค. ์์ ๋งํ ๊ฒ์ฒ๋ผ in ํค์๋๋ฅผ ํตํด์ ํด๋ก์ ํค๋์ ํด๋ก์ ๋ฐ๋๋ฅผ ๊ตฌ๋ถํ๋ค.
let alphabets = ["a", "b", "c", "d", "e"]
/*
func comparedTwoValues(_ s1: String, _ s2: String) -> Bool {
return s1 > s2 // ๋ด๋ฆผ์ฐจ์์ผ๋ก ์ ๋ ฌ
}
let reversed = alphabets.sorted(by: compareTwoValues)
*/
let reversed = alphabets.sorted(by: {(s1: String, s2: String) -> Bool in
return s1 > s2
})
print(reversed)
์ฝ๋๊ฐ ์กฐ๊ธ ๊ฐ๋จํด์ง๊ธด ํ๋๋ฐ ๋์ ๋๋ ๋ณํ๋ฅผ ๋๋ผ์ง๋ ๋ชปํ๊ฒ ๋ค.
1. ๋ ์ค์ฌ๋ณด๊ธฐ
ํด๋ก์ ๋ ์ ๋ฌ ์ธ์๋ก ์ ๋ฌ๋๊ธฐ์ Swift๊ฐ ํ๋ผ๋ฏธํฐ ํ์ ๊ณผ ๋ฐํ ๋๋ ๊ฐ์ ์ ์ถํ ์ ์๋ค.
alphabets ์์๊ฐ [String] ํ์ ์ด๋ฏ๋ก ์ ๋ฌ ์ธ์ ์ญ์, (String, String) → Bool ์ธ ๊ฒ์ ์ ์ถํ ์ ์๊ฒ ๋๋ค.
๊ฒฐ๊ณผ์ ์ผ๋ก ํ๋ผ๋ฏธํฐ ํ์ ๊ณผ ๋ฐํ ํ์ ์ ์๋ตํ ์ ์๋ค.
let reversed = alphabets.sorted(by: { s1, s2 in return s1 > s2 })
2. ๋ ๋ ์ค์ฌ๋ณด๊ธฐ
ํ ์ค๋ก ํํ ๊ฐ๋ฅํ ํด๋ก์ ๋ ์ฌ์ง์ด return๋ ์๋ต ๊ฐ๋ฅํ๋ค.
let reversed = alphabets.sorted(by: { s1, s2 in s1 > s2 })
/* ์๋ ์ฝ๋๋ ์ปดํ์ผ Error
let reversed = alphabets.sorted(by: { s1, s2 in
s1 > s2
print(s1)
})
*/
3. ๋ ๋ ๋ ์ค์ฌ๋ณด๊ธฐ
์ ์ฝ๋๋ ํด๋ก์ ํํ์์ด ์ ์ฒด ๋ฐ๋์ด๋ฏ๋ก in ํค์๋์กฐ์ฐจ ์๋ตํ ์ ์๋ค.
let reversed = alphabets.sorted(by: { $0 > $1 })
4. ๋ ๋ ๋ ๋ ์ค์ฌ๋ณด๊ธฐ
let reversed = alphabets.sorted(by: >)
ํํ ํด๋ก์
ํจ์์ ๋ง์ง๋ง ์ธ์์ ํด๋ก์ ํํ์์ ์ ๋ฌํด์ผ ํ๊ณ , ํด๋ก์ ํํ์์ด ๊ธด ๊ฒฝ์ฐ ํํ ํด๋ก์ ๋ก ์์ฑํ๋ ๊ฒ์ด ์ ์ฉํ๋ค.
์ด๋ฌํ ํํ ํด๋ก์ ๋ ์ฒซ ๋ฒ์งธ ํด๋ก์ ์ Argument Label์ ์์ฑํ์ง ์์๋ ๋๋ค.
func someFunctionThatTakesAClosure(closure: () -> Void) {
// function body goes here
}
// ์ผ๋ฐ์ ์ธ ํด๋ก์ ํํ์์ผ๋ก ์์ฑ
someFunctionThatTakesAClosure(closure: {
// closure's body goes here
})
// ํํ ํด๋ก์ ๋ก ์์ฑ
someFunctionThatTakesAClosure() {
// trailing closure's body goes here
}
๋ ๋ค๋ฅธ ์์๋ฅผ ๋ณด์. ํด๋ก์ ๋ฅผ ํตํด์ ์ค๋ฅ๋ฅผ ์ฒ๋ฆฌํ๋ ์ฝ๋๋ฅผ ๋ช ํํ๊ฒ ๋ถ๋ฆฌํ ์ ์๋ค.
func loadPicture(from server: Server, completion: (Picture) -> Void, onFailure: () -> Void) {
if let picture = download("photo.jpg", from: server) {
completion(picture)
} else {
onFailure()
}
}
// ์ฒซ ๋ฒ์งธ ํด๋ก์ ์ Argument Label์ธ completion์ ์๋ต
loadPicture(from: someServer) { picture in
someView.currentPicture = picture
} onFailure: { // ๋ ๋ฒ์งธ ํด๋ก์ ์ Argument Label์ ๊ทธ๋๋ก ์์ฑ
print("Couldn't download the next picture.")
}
์บก์ณ๊ฐ (ํด๋ก์ ๋ ์ฐธ์กฐ ํ์ )
ํด๋ก์ ๋ ์ ์๋ ์ฝ๋ ๋ธ๋ญ ๋ด์์ ์์์ ๋ณ์๋ฅผ ์บก์ณํ ์ ์๋ค.
๊ทธ๋์ ์์์ ๋ณ์๋ฅผ ์ ์ํ๋ ๋ฒ์(์ค์ฝํ)๋ฅผ ๋ฒ์ด๋๋๋ผ๋ ํด๋ก์ ์์ ํด๋น ์์์ ๋ณ์์ ๊ฐ์ ์ฐธ์กฐํ๊ณ ์์ ํ ์ ์๋ค.
๋ง์ด ์ข ์ด๋ ต์ง๋ง ์ฝ๊ฒ ์ค๋ช ํ์๋ฉด ์์์ ๋ณ์์ ์ํ๋ฅผ ๊ฐ์ง๊ณ ์์ ์ ์๋ค๋ ๋ง์ด๋ค.
์ค์ ์ฝ๋๋ฅผ ๋ณด๋ฉด์ ์ฒ์ฒํ ์ดํด๋ณด์.
func makeIncrementer(forIncrement amount: Int) -> (() -> Int) {
var runningTotal = 0
func incrementer() -> Int {
runningTotal += amount
return runningTotal
}
return incrementer
}
makeIncrementer ํจ์๋ ํด๋ก์ ๋ฅผ ๋ฆฌํดํ๊ณ ์๋ค. ๋ด๋ถ์ runningTotal ๋ณ์๊ฐ ์ ์๋์ด ์๊ณ ์ค์ฒฉ ํจ์์ธ incrementer ํจ์์์๋ runningTotal์ ์ ๋ฌ์ธ์๋ก ๋ฐ์ amount๋งํผ ๋ ํด์ค๋ค.
์ด์ ์ด ํจ์๋ฅผ incrementByTen ์์์ ํ ๋นํ๊ณ ํธ์ถํด๋ณด์.
let incrementByTen = makeIncrementer(forIncrement: 10)
incrementByTen()
incrementByTen()
print(incrementByTen())
์ด๋ค ๊ฐ์ด ์ถ๋ ฅ๋ ๊น?
์ ๋ต์ 30์ด๋ค.
10 + 10 + 10 (print๋ก ์ถ๋ ฅ๋๊ธฐ ์ ์ ํ๋ฒ ๋ ํธ์ถ)
์ค์ฒฉ ํจ์์ธ incrementer ํจ์๋ ๋งค๊ฐ๋ณ์๋ก runningTotal์ ์ง์ ์ ์ผ๋ก ์ ๋ฌ ๋ฐ์ง๋ ์์ง๋ง runningTotal๊ณผ amount๋ฅผ ์ฐธ์กฐ๋ฅผ ์บก์ณํ๊ณ ์ด๋ฅผ ํจ์ ๋ด์์ ์ฌ์ฉํ๊ณ ์๋ค.
๊ทธ ๊ฒฐ๊ณผ ํจ์๊ฐ ์ข ๋ฃ๋๋๋ผ๋ ์ด์ ํธ์ถ ๊ฒฐ๊ณผ๊ฐ ์ฌ๋ผ์ง์ง ์๊ณ ๋ค์์ ํธ์ถ๋ ๋ ์ด ๊ฐ์ ์ฌ์ฉํ ์ ์๋ ๊ฒ์ด๋ค.
๊ทธ๋ ๋ค๋ฉด ์๋์ ์ฝ๋์ ๊ฒฐ๊ณผ๋ ์ด๋ค ๊ฐ์ด ์ถ๋ ฅ๋ ๊น?
let incrementByTen = makeIncrementer(forIncrement: 10)
incrementByTen()
incrementByTen()
print(incrementByTen()) // 30
let alsoIncrementByTen = incrementByTen
alsoIncrementByTen()
alsoIncrementByTen()
print(incrementByTen())
์ ๋ต์ 60์ด๋ค.
์์ ๋งํ๋ ๊ฒ์ฒ๋ผ ํด๋ก์ ๋ ๋ด๋ถ์ ์์์ ๋ณ์์ ๋ํ ์ฐธ์กฐ๋ฅผ ์บก์ณํ๊ณ ์๋ค.
alsoIncrementByTen ์ญ์ ๊ฐ์ ํด๋ก์ ๋ฅผ ์ฐธ์กฐํ๊ณ ์๊ธฐ์ ์ด๋ค ์์๋ฅผ ํธ์ถํ๋ ๊ฐ์ ํด๋ก์ ๊ฐ ์คํ๋๋ ๊ฒ์ด๋ค.
์ด๊ฑธ ํตํด ํด๋ก์ ๋ ์ฐธ์กฐ ํ์ ์ด๋ผ๋ ๊ฒ์ ์ ์ ์๋ค.
์ด์ค์ผ์ดํ ํด๋ก์
ํจ์์ ์ธ์๋ก ํด๋ก์ ๋ฅผ ์ ๋ฌํ๊ณ ํจ์ ๋ฐ์ ๋ณ์์ ํด๋ก์ ๋ฅผ ํ ๋นํ๊ฑฐ๋ ํจ์๊ฐ ์ข ๋ฃ๋ ๋ค์ ์คํ๋๋ ํด๋ก์ ๋ฅผ ์ด์ค์ผ์ดํ ํด๋ก์ ๋ผ๊ณ ํ๋ค.
์ฐ์ ํด๋ก์ ๊ฐ ์๋ ์ผ๋ฐ์ ์ธ ์ฝ๋๋ฅผ ๊ธฐ์ค์ผ๋ก ์ดํด๋ณด์.
class Test {
var num: Int? // ์ ์ญ
func setNumber(number: Int) {
self.num = number
}
}
์ด์ฒ๋ผ ํจ์ ๋ด๋ถ์์ ์ ๋ฌ์ธ์๋ฅผ ์ ์ญ ๋ณ์์ธ num์ ํ ๋นํ๋ ๊ฒ์ ์๋ฌด๋ฐ ๋ฌธ์ ๊ฐ ๋์ง ์๋๋ค.
๊ทธ๋ ๋ค๋ฉด ์๋ ์ฝ๋๋ ์ด๋จ๊น?
class Test {
var closure: (() -> Void)?
func setClosure(_ param: () -> Void) {
self.closure = param
}
}
non-escaping parameter๋ฅผ escaping closure์ ํ ๋นํ ์ ์๋ค๋ ์ค๋ฅ๊ฐ ๋ฐ์ํ๋ค.
๊ทธ๋ ๋ค๋ฉด escaping ์ด๋ ธํ ์ด์ ์ด ํ์ํ ์ด์ ๋ ๋ฌด์์ผ๊น?
์์ ๋งํ๋ ๊ฒ์ฒ๋ผ ํด๋ก์ ๋ ์ฐธ์กฐ ํ์ ์ด๊ณ ํจ์ ๋ด๋ถ์์ ๊ฐ์ด ํ ๋น๋์ ๋ ์คํํ๋ ๊ฒ์ด ์๋๋ผ ์ธ๋ถ์์ ํธ์ถ๋์ ๋ ์คํํ๊ฒ ๋๋ค.
์ฆ, ํด๋ก์ ๊ฐ ์ ๋ฌ๋๋ ํจ์๋ณด๋ค ๋ ์ค๋ ์ง์๋์ด์ผ ํ๋๋ฐ ์ด๋ฅผ ๋์์ฃผ๋ ๊ฒ์ด escaping ์ด๋ ธํ ์ด์ ์ด๋ค.
class Test {
var closure: (() -> Void)?
func setClosure(_ param: @escaping () -> Void) {
self.closure = param
}
}
escaping ์ด๋ ธํ ์ด์ ์ ์ถ๊ฐํ๋ฉด ์ ์์ ์ผ๋ก ์ปดํ์ผ์ด ๋๋ค.
๐ ์ฐธ๊ณ ํ ๊ฒ
๐ ํ๊ณ
์ค๋ "ํจ๊ป ์๋ผ๊ธฐ" ์คํฐ๋๋ฅผ ์งํํ๋ฉด์ ์คํ ํ๋ ์๊ณผ ํ์ต ํ๋ ์์ ๋ํด ์๊ฒ ๋๋ค. ๋ ๊ตฐ์ง์ ๋ํ ์คํ๊ณผ ์๋ก ์๋ฐ๋ ์์ธ์ ๋ ๋ช ์ ๊ฐ๋ฐ์๋ฅผ ๋ณด๋ฉด์ ๋ ์ญ์, '์๋ผ๊ธฐ' ๋ณด๋ค๋ '์ํ๊ธฐ'์ ์ด์ ์ ๋ง์ถฐ์ ์ง๋ด์๋ค. ๊ฐ์ฅ ์ต๊ทผ์ ์ํ๋ NC ์ธํด์์๋ ์ ํ๋ ๊ธฐ๊ฐ ์์ ๊ณผ์ ๋ฅผ ์ํํด์ผ ํ๋ค๋ ์๋ฐ๊ฐ์ '์ํ๊ธฐ'๋ง ์๊ฐํ๊ณ '์๋ผ๊ธฐ'๋ ์ค์ค๋ก ํ๊ณ๋ฅผ ๋๋ฉฐ ๋ค์ ๋ฉ๋ฆฌํ ๊ฒฝํฅ์ด ์์๋ค. "์คํ ํ๋ ์๊ณผ ํ์ต ํ๋ ์" ํํธ๋ฅผ ์ฝ์ผ๋ฉด์ ์ง์ ํ ์ฑ์ฅ์ด ๋ฌด์์ธ๊ฐ์ ๋ํด ๋ค์ ํ ๋ฒ ์๊ฐํ๋ ๊ณ๊ธฐ๊ฐ ๋์๋ค.
'๐ป ๊ฐ๋ฐ > iOS' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[iOS / SwiftUI] ํค๋ณด๋๊ฐ ์ฌ๋ผ์ง์ง ์์์...๐ฉ (0) | 2022.10.21 |
---|---|
[iOS / SwiftUI] ForEach๋ก View๋ฅผ ๋ฆฌํํ ๋ง ํด๋ณผ๊น์? (0) | 2022.10.11 |
[iOS / Swift] ํด๋ก์ ์ ํ๋กํผํฐ, ๊ฐ๋ณ๊ฒ ์์๋ณด๊ธฐ (0) | 2022.10.02 |
[iOS / Swift] ์์ VS ์ต์คํ ์ (0) | 2022.09.27 |
[TIL] 22.08.25 (0) | 2022.08.25 |