πŸ¦… Swift

Closures

KiwiπŸ’» 2022. 6. 15. 20:19

ν΄λ‘œμ €λŠ” 주변에 μ „λ‹¬λ˜κ±°λ‚˜, μ½”λ“œμ—μ„œ μ‚¬μš©λ  수 μžˆλŠ” κΈ°λŠ₯ λΈ”λŸ­μ„ λ§ν•œλ‹€. ν΄λ‘œμ €λŠ” μ •μ˜λœ λ¬Έμž₯μ•ˆμ—μ„œ μƒμˆ˜μ™€ λ³€μˆ˜μ— λŒ€ν•œ 참쑰값을 캑처 ν•  수 μžˆλ‹€. μŠ€μœ„ν”„νŠΈλŠ” 캑처된 λ©”λͺ¨λ¦¬λ₯Ό 관리할 수 μžˆλŠ” λͺ¨λ“  κΈ°λŠ₯을 μ œκ³΅ν•œλ‹€.

μ „μ—­ν•¨μˆ˜μ™€ μ€‘μ²©ν•¨μˆ˜λŠ” ν΄λ‘œμ €μ˜ λ‹€λ₯Έ 이름이닀. ν΄λ‘œμ €λŠ” μ•„λž˜ 세가지 ν˜•νƒœμ€‘ ν•˜λ‚˜μ˜ ν˜•νƒœλ₯Ό μ·¨ν•œλ‹€.

  • μ „μ—­ν•¨μˆ˜λŠ” 이름을 가지고 μžˆμœΌλ‚˜ 값을 μΊ‘μ²˜ν•˜μ§€ μ•ŠλŠ” ν΄λ‘œμ €μ΄λ‹€.
  • μ€‘μ²©ν•¨μˆ˜λŠ” 이름을 가지고 있고 λ‚΄λΆ€μ˜ ν•¨μˆ˜λ‘œλΆ€ν„° 값을 μΊ‘μ²˜ν•  수 μžˆλŠ” ν΄λ‘œμ €μ΄λ‹€.
  • ν΄λ‘œμ €ν‘œν˜„μ‹μ€ μ£Όλ³€ λ¬Έμž₯μœΌλ‘œλΆ€ν„° 값을 캑쳐할 수 μžˆλŠ” 이름이 μ—†λŠ” κ²½λŸ‰κ΅¬λ¬Έμ„ λ§ν•œλ‹€.

μŠ€μœ„ν”„νŠΈμ—μ„œ ν΄λ‘œμ €ν‘œν˜„μ‹μ€ κ°„κ²°ν•˜κ³  κΉ”λ”ν•˜κ³  λͺ…λ°±ν•œ μŠ€νƒ€μΌμ„ μΆ”κ΅¬ν•œλ‹€. ν΄λ‘œμ €μ˜ μ΅œμ ν™”λŠ” λ‹€μŒμ„ ν¬ν•¨ν•œλ‹€.

  • λ¬Έμž₯을 톡해 νŒŒλΌλ―Έν„°μ™€ 리턴 값을 μœ μΆ”ν•œλ‹€.
  • λ‹¨μΌμ˜ ν΄λ‘œμ €λ‘œ λΆ€ν„° 리턴값을 μ•”μ‹œμ μœΌλ‘œ λ°˜ν™˜ν•œλ‹€.
  • κ°„λ‹¨ν•œ μ•„κ·œλ¨ΌνŠΈ 이름
  • ν›„ν–‰ ν΄λ‘œμ € ꡬ문

ν΄λ‘œμ € ν‘œν˜„μ‹ (Closure Expressions)

μ€‘μ²©ν•¨μˆ˜λŠ” μƒμœ„ ν•¨μˆ˜μ— λ‚΄ν¬λœ ν•¨μˆ˜μ˜ 이름을 μ •μ˜ν•˜κΈ°μ— νŽΈλ¦¬ν•˜λ‹€. κ·ΈλŸ¬λ‚˜ λ•Œλ•Œλ‘œ κ°„λ‹¨ν•œ μˆ˜μ€€μ˜ ν•¨μˆ˜λ₯Ό μ™„μ „ν•œ μ„ μ–Έκ³Ό 이름없이 κ΅¬ν˜„ν•˜λŠ” 것이 νŽΈλ¦¬ν•  λ•Œλ„ μ‘΄μž¬ν•œλ‹€. 특히 λ‹€μˆ˜μ˜ μ•„κ·œλ¨ΌνŠΈλ₯Ό 가지고 μžˆλŠ” ν•¨μˆ˜λ₯Ό μ‚¬μš©ν• λ•Œ λ”μš± κ·Έλ ‡λ‹€.

ν΄λ‘œμ € ν‘œν˜„μ‹μ΄λž€ 인라인 ν΄λ‘œμ €λ‘œ 식을 λ”μš± λ‹¨μˆœν•˜κ³  κ°„κ²°ν•˜κ²Œ λ‚˜νƒ€λ‚΄λŠ” 것이닀. ν΄λ‘œμ € ν‘œν˜„μ‹μ€ λͺ…ν™•μ„±κ³Ό μ˜λ„λ₯Ό μžƒμ§€ μ•Šκ³  ν΄λ‘œμ €λ₯Ό λ”μš± κ°„κ²°ν•˜κ²Œ λ‚˜νƒ€λ‚Ό 수 있게 μ΅œμ ν™” λ˜μ—ˆλ‹€.

//λ¬Έλ§₯μ—μ„œ νƒ€μž… μΆ”λ‘ 
//단일 ν‘œν˜„ ν΄λ‘œμ €μ—μ„œμ˜ μ•”μ‹œμ  λ°˜ν™˜
//인자 이름 μΆ•μ•½
var number = [1, 4, 5, 2, 3, 7, 8, 6]

print(number.sorted(by: { (s1: Int, s2: Int) -> Bool in return s1 > s2 } ))
// ν΄λ‘œμ €μ˜ κΈ°λ³Έ ν‘œν˜„λ²• by 의 λ§€κ°œλ³€μˆ˜ κ°’μœΌλ‘œ ν΄λ‘œμ €λ₯Ό μ‚¬μš©
// λ¬Έλ§₯μ—μ„œ νƒ€μž… μΆ”λ‘ 
print(number.sorted(by: {s1, s2 in return s1 > s2}))
/* sorted(by:)의 λ©”μ†Œλ“œμ—μ„œ 이미 (Int, Int) -> Bool νƒ€μž…μ˜ μΈμžκ°€ 듀어와야 ν•˜λŠ”κ±Έ
 μ•ŒκΈ° λ•Œλ¬Έμ— ν΄λ‘œμ €μ—μ„œ 이 νƒ€μž…λ“€μ€ μƒλž΅μ΄ κ°€λŠ₯ν•˜λ‹€.*/

// 단일 ν‘œν˜„ ν΄λ‘œμ €μ—μ„œμ˜ μ•”μ‹œμ  λ°˜ν™˜
print(number.sorted(by: { s1, s2 in s1 > s2 } ))
// return ν•˜λŠ” 값이 ν•˜λ‚˜μΌ κ²½μš°μ— return μƒλž΅μ΄ κ°€λŠ₯
// 인자 이름 μΆ•μ•½
print(number.sorted(by: { $0 > $1 } ))
// 값을 μˆœμ„œλŒ€λ‘œ $0, $1, $2 λ“±μœΌλ‘œ ν‘œν˜„ν•˜μ—¬ 인자 μž…λ ₯λΆ€λΆ„κ³Ό in ν‚€μ›Œλ“œ 뢀뢄을 μƒλž΅

ν›„ν–‰ ν΄λ‘œμ € (Trailing Closures)

ν•¨μˆ˜λ₯Ό λ§ˆμ§€λ§‰ μ•„κ·œλ¨ΌνŠΈλ‘œ λ°›λŠ” ν•¨μˆ˜μ—μ„œλŠ” ν›„ν–‰ ν΄λ‘œμ € 문법을 μ‚¬μš©ν•˜λŠ” 것이 μ’‹λ‹€.

func someFunctionThatTakesAClosure(closure: () -> Void) {
    // ν•¨μˆ˜ λ‚΄μš©
}

// ν›„ν–‰ν΄λ‘œμ €λ₯Ό μ‚¬μš©ν•˜μ§€ μ•Šκ³  ν•¨μˆ˜λ₯Ό κ΅¬ν˜„ν•˜λŠ” 방법

someFunctionThatTakesAClosure(closure: {
    // ν•¨μˆ˜ λ‚΄μš©
})

// ν›„ν–‰ν΄λ‘œμ €λ₯Ό μ‚¬μš©ν•˜κ³  ν•¨μˆ˜λ₯Ό κ΅¬ν˜„ν•˜λŠ” 방법

someFunctionThatTakesAClosure() {
    // ν›„ν–‰ν΄λ‘œμ €λ₯Ό μ‚¬μš©ν•œ ν•¨μˆ˜ λ‚΄μš©
}

ex) reversedNames = names.sorted { $0 > $1 }

μΊ‘μ²˜κ°’ (Capturing Values)

ν΄λ‘œμ €λŠ” μ„ μ–Έλœ λ¬Έμž₯ μ£Όλ³€μœΌλ‘œλΆ€ν„° μƒμˆ˜μ™€ λ³€μˆ˜λ₯Ό μΊ‘μ²˜ν•  수 μžˆλ‹€. 그리고 ν΄λ‘œμ €λŠ” μƒμˆ˜μ™€ λ³€μˆ˜κ°€ μ •μ˜λœ μ›λž˜ λ²”μœ„κ°€ 더이상 μ‘΄μž¬ν•˜μ§€ μ•Šλ”λΌλ„ ν΄λ‘œμ € λ‚΄μ—μ„œ ν•΄λ‹Ή μƒμˆ˜μ™€ λ³€μˆ˜μ˜ 값을 μ°Έμ‘°ν•˜κ³  μˆ˜μ •ν•  수 μžˆλ‹€.

func makeIncrementer(forIncrement amount: Int) -> () -> Int {
    var runningTotal = 0
    func incrementer() -> Int {
        runningTotal += amount
        return runningTotal
    }
    return incrementer
}

incrementer() ν•¨μˆ˜λŠ” νŒŒλΌλ―Έν„°κ°€ μ—†μœΌλ©° ν•¨μˆ˜ 바디내에 runningTotal κ³Ό amount λ₯Ό μ°Έμ‘°ν•˜κ³  μžˆλ‹€. runningTotal κ³Ό amountλ₯Ό μΊ‘μ²˜ν•˜κ³  ν•¨μˆ˜ λ‚΄μ—μ„œ μ‚¬μš©ν•œλ‹€. μ°Έμ‘°λ₯Ό μΊ‘μ²˜ν•˜λŠ” 것은 makeIncrementer 호좜이 μ’…λ£Œλ μ§€λΌλ„ runningTotal κ³Ό amountκ°€ 사라지지 μ•Šκ³  λ‹€μŒμ— incrementer ν•¨μˆ˜κ°€ 호좜될 λ•Œ runningTotalλ₯Ό κ·ΈλŒ€λ‘œ μ‚¬μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

let incrementByTen = makeIncrementer(forIncrement: 10)
incrementByTen()
// returns a value of 10
incrementByTen()
// returns a value of 20
incrementByTen()
// returns a value of 30

Note❗️
ν΄λ‘œμ €λŠ” μ°Έμ‘° νƒ€μž…μ΄λ‹€.

μ΄μŠ€μΌ€μ΄ν”„ ν΄λ‘œμ € (Escaping Closures)

μΌλ°˜μ μœΌλ‘œλŠ” ν•¨μˆ˜μ˜ 싀행이 μ’…λ£Œλ˜λ©΄ νŒŒλΌλ―Έν„°λ‘œ μ“°μ΄λŠ” ν΄λ‘œμ €λŠ” μ œκ±°κ°€ λœλ‹€. κ·Έλž˜μ„œ ν΄λ‘œμ €μ˜ 싀행을 μ™ΈλΆ€ λ³€μˆ˜μ— μ €μž₯ν•˜μ—¬ 본래의 ν•¨μˆ˜λ₯Ό λ²—μ–΄λ‚˜λ„ μ‹€ν–‰ν•˜λ„λ‘ ν•˜κΈ° μœ„ν•΄μ„œλŠ” @escaping ν‚€μ›Œλ“œκ°€ ν•„μš”ν•˜λ‹€.

// λ‹¨μˆœμ‹€ν–‰
func normalClosuer(closure: () -> ()) {
    print("ν”„λ¦°νŠΈ μ‹œμž‘")
    closure()
}

normalClosuer {
    print("ν”„λ¦°νŠΈ μ’…λ£Œ")
}

-> ν”„λ¦°νŠΈ μ‹œμž‘, ν”„λ¦°νŠΈ μ’…λ£Œκ°€ κ·ΈλŒ€λ‘œ ν”„λ¦°νŠΈ 됨

var function1 : () -> () = { print("좜λ ₯") }

function1()
-> "좜λ ₯"을 ν”„λ¦°νŠΈ 함

func performEscaping(closure: @escaping () -> ()) {
    function1 = closure         
    // function1 λ³€μˆ˜μ—ν• λ‹Ή
}

performEscaping(closure: { print("λ‹€λ₯΄κ²Œ 좜λ ₯") })
-> "λ‹€λ₯΄κ²Œ 좜λ ₯"을 ν”„λ¦°νŠΈ ν•˜λŠ” 것이 μ•„λ‹Œ function1에 ν• λ‹Ήλ§Œ ν•˜κ²Œλ¨

function1()
-> 본래의 ν•¨μˆ˜λ₯Ό λΉ μ Έλ‚˜μ™€μ„œλ„ "λ‹€λ₯΄κ²Œ 좜λ ₯" ν”„λ¦°νŠΈ 함

캑처리슀트

ν΄λ‘œμ € μ™ΈλΆ€μ˜ λ³€μˆ˜λ₯Ό μ‚¬μš©ν•˜κΈ° μœ„ν•΄ λ³€μˆ˜λ₯Ό μΊ‘μ²˜ν•˜λŠ” ν˜„μƒμ΄ λ°œμƒν•œλ‹€. μ΄λŠ” μ™ΈλΆ€ λ³€μˆ˜μ˜ μ£Όμ†Œλ₯Ό μ°Έμ‘°ν•˜λŠ” ν˜•νƒœλ‘œ 이루어 진닀. ν•˜μ§€λ§Œ 캑처리슀트λ₯Ό μ‚¬μš©ν•˜λ©΄ λ³€μˆ˜μ˜ μ£Όμ†Œλ₯Ό κ°€μ Έμ˜€λŠ” 것이 μ•„λ‹Œ κ°’ 자체λ₯Ό λ³΅μ‚¬ν•΄μ„œ κ°€μ Έμ˜€κ²Œ λœλ‹€.(κ°’νƒ€μž…μ˜ 경우)

μ°Έμ‘°νƒ€μž…μ˜ 캑처리슀트

class SomeClass {
    var num = 0
}

var x = SomeClass()
var y = SomeClass()

print("μ°Έμ‘° μ΄ˆκΈ°κ°’(μ‹œμž‘κ°’):", x.num, y.num)

let refTypeCapture = { [x] in
    print("μ°Έμ‘° 좜λ ₯κ°’(캑처리슀트):", x.num, y.num)
}

// μ•½ν•œμ°Έμ‘° μ‚¬μš©λ°©λ²•
ex) let refTypeCapture = { [weak x] in
    print("μ°Έμ‘° 좜λ ₯κ°’(캑처리슀트):", x?.num, y.num)
}

이 경우 xλŠ” someClassλ‚΄μ˜ numν”„λ‘œνΌν‹° 자체의 μ£Όμ†Œλ₯Ό κ°€μ Έμ™€μ„œ μ§μ ‘μ μœΌλ‘œ μ°Έμ‘°ν•˜κ²Œ λ˜λ‚˜(RC2), y의 κ²½μš°λŠ” yλ³€μˆ˜μ˜ μ£Όμ†Œλ₯Ό λ¨Όμ € μ°Έμ‘°ν•œλ‹€μŒ num의 μ£Όμ†Œκ°’μ„ μ°Έμ‘°ν•˜κ²Œ λœλ‹€(RC1). κ·ΈλŸ¬λ―€λ‘œ μ°Έμ‘°νƒ€μž…μ˜ 캑처리슀트λ₯Ό μ‚¬μš©ν•  λ•Œμ—λŠ” μˆœν™˜μ°Έμ‘°μ— μ˜ν•œ λ©”λͺ¨λ¦¬ λˆ„μˆ˜μ— μœ μ˜ν•΄μ•Όν•œλ‹€.

'πŸ¦… Swift' μΉ΄ν…Œκ³ λ¦¬μ˜ λ‹€λ₯Έ κΈ€

Structures and Classes  (0) 2022.06.22
Enumerations  (0) 2022.06.15
Functions  (0) 2022.06.01
Control Flow  (0) 2022.06.01
Collection Types  (0) 2022.05.22