[Swift🦩] #7 ν΄λ‘œμ €

λ˜μƒΒ·2022λ…„ 3μ›” 25일
0

iOS

λͺ©λ‘ 보기
23/47
post-thumbnail
  • πŸ“• ν•¨μˆ˜ν˜• ν”„λ‘œκ·Έλž˜λ°μ— μžˆμ–΄μ„œ μ•„μ£Ό μ€‘μš”!!!
    • ν•¨μˆ˜μ˜ 전달 인자둜 ν΄λ‘œμ €(ν•¨μˆ˜) λ₯Ό λ³΄λ‚Έλ‹€λ˜κ°€,
  • μ½”λ“œμ—μ„œ 주변에 전달, μ‚¬μš©ν•  수 μžˆλŠ” κΈ°λŠ₯ λΈ”λŸ­. inline function
  • C의 λΈ”λŸ­κ³Ό 파이썬의 λžŒλ‹€μ™€ μœ μ‚¬ν•˜λ‹€.
  • μ •μ˜λœ μ»¨ν…μŠ€νŠΈμ—μ„œ λͺ¨λ“  μƒμˆ˜μ™€ λ³€μˆ˜μ— λŒ€ν•œ μ°Έμ‘°λ₯Ό μΊ‘μ²˜ν•˜κ³  μ €μž₯ν•  수 μžˆλ‹€. -> 이런 μƒμˆ˜μ™€ λ³€μˆ˜λ₯Ό closing over 라고 ν•˜κ³ , 캑처된 μƒμˆ˜μ™€ λ³€μˆ˜μ— λŒ€ν•œ λ©”λͺ¨λ¦¬ κ΄€λ¦¬λŠ” μžλ™μœΌλ‘œ 이루어진닀.

λ©”λͺ¨λ¦¬ 관리 λ•Œλ¬Έμ— 항상 weak self λ₯Ό μ‚¬μš©ν•˜κ³  μžˆμ—ˆλ‹€.

μ’…λ₯˜μ΄λ¦„μΊ‘쳐
μ „μ—­ ν•¨μˆ˜OX
쀑첩 ν•¨μˆ˜Oλ‘˜λŸ¬μ¬ ν•¨μˆ˜ λ‚΄μ—μ„œ 캑쳐 κ°€λŠ₯
ν΄λ‘œμ € ν‘œν˜„μ‹Xμ£Όλ³€ μ»¨ν…μŠ€νŠΈμ—μ„œ O

-> ν΄λ‘œμ € ν‘œν˜„μ‹μ„ μ΄μš©ν•˜λ©΄ κΉ”λ”ν•œ ꡬ문을 μ΄μš©ν•  수 μžˆλ‹€.


πŸ“• ν΄λ‘œμ €μ˜ μ„Έ 가지 ν˜•νƒœ
1. 이름이 있고 μ–΄λ–€ 값도 νšλ“ν•˜μ§€ μ•ŠμŒ - μ „μ—­ν•¨μˆ˜
2. 이름이 있고 λ‹€λ₯Έ ν•¨μˆ˜ λ‚΄λΆ€μ˜ 값을 νšλ“ - μ€‘μ²©ν•¨μˆ˜
3. 이름이 μ—†κ³  μ£Όλ³€ λ¬Έλ§₯에 따라 값을 νšλ“ - μΆ•μ•½ 문법


1. ν΄λ‘œμ € ν‘œν˜„μ‹ ⭐️

sorted(by: ) λ₯Ό μ˜ˆμ‹œλ‘œ μ„€λͺ….
λ‹€λ₯Έ μ–Έμ–΄λ“€ 처럼, sorted μ—λŠ” μ•ž, λ’€ 두 인자λ₯Ό λΉ„κ΅ν•΄μ„œ Bool 값을 λ°˜ν™˜(첫번째 값이 μ•žμ΄λ©΄ true, λ‘λ²ˆμ§Έ 값이 μ•žμ΄λ©΄ false λ°˜ν™˜)ν•˜λŠ” ν΄λ‘œμ €λ₯Ό λ„£μ–΄μ£Όλ©΄ λœλ‹€.

let names = ["Chris", "Alex", "Ewa", "Barry", "Daniella"]

1. ν•¨μˆ˜λ‘œ 전달

func backward(_ s1: String, _ s2: String) -> Bool {
    return s1 > s2
}
var reversedNames = names.sorted(by: backward)
// reversedNames is equal to ["Ewa", "Daniella", "Chris", "Barry", "Alex"]

2. ν΄λ‘œμ € μ‚¬μš©

RxSwift 의 Observable 을 λ¦¬ν„΄ν•œλ‹€λ˜κ°€ ν•˜λŠ” λ³΅μž‘ν•œ ν΄λ‘œμ €λŠ” return type 은 λͺ…μ‹œν•΄μ€„ ν•„μš”κ°€ μžˆλ‹€.
πŸ“• λ§€κ°œλ³€μˆ˜ 이름을 μ§€μ •ν•˜λ©΄ κ°€λ³€ λ§€κ°œλ³€μˆ˜λ„ μ‚¬μš© κ°€λŠ₯!

reversedNames = names.sorted(by: { (s1: String, s2: String) -> Bool in
    return s1 > s2
})

// νƒ€μž… μœ μΆ”
reversedNames = names.sorted(by: { s1, s2 in
    return s1 > s2
})

// μ•”μ‹œμ  λ°˜ν™˜
reversedNames = names.sorted(by: { s1, s2 in 
    s1 > s2 
})

// 짧은 인자 이름
reversedNames = names.sorted(by: { $0 > $1 } )

// μ—°μ‚°μž λ©”μ„œλ“œ : 이건 μ—°μ‚°μžμΈ 경우.
reversedNames = names.sorted(by: >)

3. ν›„ν–‰ ν΄λ‘œμ € ⭐️

  • ν•¨μˆ˜μ˜ μΈμžκ°€ ν΄λ‘œμ € ν•˜λ‚˜ 뿐이라면 κ΄„ν˜Έλ₯Ό μƒλž΅ν•  수 μžˆλ‹€.
reversedNames = names.sorted { $0 > $1 }
  • ν΄λ‘œμ €κ°€ μ•„λ‹Œ μΈμžκ°€ μ•žμ— 더 μžˆλ‹€λ©΄?
loadPicture(from: someServer) { picture in
    someView.currentPicture = picture
}
  • ν΄λ‘œμ € μΈμžκ°€ μ—¬λŸ¬κ°œλΌλ©΄?
loadPicture(from: someServer) { picture in
    someView.currentPicture = picture
} onFailure: {
    print("Couldn't download the next picture.")
}

2. μΊ‘μ²˜κ°’ ⭐️⭐️

  • ν΄λ‘œμ €λŠ” μ£Όλ³€ μ»¨ν…μŠ€νŠΈμ—μ„œ μƒμˆ˜, λ³€μˆ˜λ₯Ό 캑쳐할 수 μžˆλ‹€
  • == μ›λž˜ λ²”μœ„κ°€ μ‘΄μž¬ν•˜μ§€ μ•Šλ”λΌλ„ μƒμˆ˜, λ³€μˆ˜λ₯Ό μ°Έμ‘°ν•˜κ³  μˆ˜μ •ν•  수 있음.
    πŸ“• 비동기 μž‘μ—…μ— μ΄μš©λœλ‹€. 미리 캑쳐해두지 μ•ŠμœΌλ©΄ μ‹€μ œλ‘œ μ‹€ν–‰ν•˜λ €κ³  ν•  λ•ŒλŠ” ν•΄λ‹Ή 값이 없을 μˆ˜κ°€ 있기 λ•Œλ¬Έ!

캑쳐 μ˜ˆμ‹œ - 쀑첩 ν•¨μˆ˜

  • runningTotal μΊ‘μ³λ˜μ–΄, runningTotal 을 μ°Έμ‘°ν•΄μ„œ μˆ˜μ •ν•˜κΈ° λ•Œλ¬Έμ—, runningTotal 의 κ°’ μžμ²΄κ°€ 바뀐닀.
    πŸ“• incrementer λŠ” 혼자 λ–Όμ–΄λ†“μœΌλ©΄ μž‘λ™ν•  μˆ˜κ°€ μ—†λŠ” ν•¨μˆ˜λ‹€. μ£Όλ³€μ˜ 값을 μΊ‘μ³ν•˜κΈ° λ•Œλ¬Έμ— μž‘λ™!!
func makeIncrementer(forIncrement amount: Int) -> () -> Int {
    var runningTotal = 0
    func incrementer() -> Int {
        runningTotal += amount
        return runningTotal
    }
    return incrementer
}

let incrementByTen = makeIncrementer(forIncrement: 10)

incrementByTen()
// returns a value of 10
incrementByTen()
// returns a value of 20
incrementByTen()
// returns a value of 30

// μƒˆλ‘œμš΄ 참쑰에 μ €μŸλœλ‹€.
let incrementBySeven = makeIncrementer(forIncrement: 7)
incrementBySeven()
// returns a value of 7

3. μ°Έμ‘°νƒ€μž… ⭐️⭐️

  • μœ„μ—μ„œ ν•œλ²ˆ ν• λ‹Ήν•œ ν•¨μˆ˜μ˜ runningTotal 이 계속 μ¦κ°€ν•˜λŠ” μ΄μœ λŠ” ν΄λ‘œμ €κ°€ μ°Έμ‘°νƒ€μž… 이기 λ•Œλ¬Έμ΄λ‹€.
  • κ·Έλž˜μ„œ μƒˆλ‘œμš΄ λ³€μˆ˜μ— 같은 ν΄λ‘œμ €λ₯Ό ν• λ‹Ήν•˜λ©΄ 같은 ν΄λ‘œμ €κ°€ μ°Έμ‘°λ˜μ–΄, 같은 runningTotal 이 참쑰됨.
let alsoIncrementByTen = incrementByTen
alsoIncrementByTen()
// returns a value of 50

incrementByTen()
// returns a value of 60

4. escape closure ⭐️⭐️

  • ν•¨μˆ˜κ°€ λ°˜ν™˜λœ 후에 ν˜ΈμΆœλ˜λŠ” ν΄λ‘œμ €.
    • ν•¨μˆ˜μ—μ„œ ν΄λ‘œμ €λ₯Ό λ°˜ν™˜ν•˜κ±°λ‚˜,
    • ν•¨μˆ˜ μ™ΈλΆ€ λ³€μˆ˜μ— ν•΄λ‹Ή ν΄λ‘œμ €κ°€ μ €μž₯λ˜λŠ” 경우
  • λΉ„λ™κΈ°μ μœΌλ‘œ μ‹€ν–‰λ˜μ–΄μ•Ό ν•˜λŠ” μž‘μ—…μ˜ 경우,
    ν•¨μˆ˜λŠ” λλ‚¬λŠ”λ°, λΉ„λ™κΈ°μ μœΌλ‘œ 데이터λ₯Ό λ°›λŠ” μž‘μ—…μ€ λλ‚˜μ§€ μ•ŠλŠ” κ²½μš°κ°€ 많음.
  • κ·Έλž˜μ„œ 데이터λ₯Ό λ°›λŠ” μž‘μ—…μ΄ λλ‚˜κ³  무언가λ₯Ό μ²˜λ¦¬ν•  λ•Œ ν•¨μˆ˜μ— ν΄λ‘œμ €λ₯Ό μ „λ‹¬ν•΄μ„œ μ΄μš©ν•˜λŠ”λ°,
  • 이런 ν•¨μˆ˜κ°€ λλ‚˜κ³  λ‚˜μ„œ μ‹€ν–‰λ˜λŠ” ν΄λ‘œμ €μ—λŠ” @escaping μ΄λΌλŠ” ν‚€μ›Œλ“œλ₯Ό μ¨μ€˜μ•Ό ν•œλ‹€.
  • escaping clousure μ—μ„œ self λ₯Ό μ‚¬μš©ν•  λ•ŒλŠ” μˆœν™˜ 참쑰에 μ£Όμ˜ν•˜μž!!
  • μ™œλƒν•˜λ©΄, escaping ν΄λ‘œμ €λ₯Ό μ‚¬μš©ν•  λ•ŒλŠ” λͺ…μ‹œμ μœΌλ‘œ self λ₯Ό μ¨μ•Όν•˜κΈ° λ•Œλ¬Έ.
var completionHandlers: [() -> Void] = []
func someFunctionWithEscapingClosure(completionHandler: @escaping () -> Void) {
    completionHandlers.append(completionHandler)
}

func someFunctionWithNonescapingClosure(closure: () -> Void) {
    closure()
}

class SomeClass {
    var x = 10
    func doSomething() {
        someFunctionWithEscapingClosure { self.x = 100 }
        // someFunctionWithEscapingClosure { [self] in x = 100 }
        someFunctionWithNonescapingClosure { x = 200 }
    }
}

let instance = SomeClass()
instance.doSomething()
print(instance.x)
// Prints "200"

completionHandlers.first?()
print(instance.x)
// Prints "100"

πŸ“• withoutActuallyEscaping

  • λΉ„νƒˆμΆœ ν΄λ‘œμ €λ‘œ μ „λ‹¬ν•œ ν΄λ‘œμ €κ°€ νƒˆμΆœ ν΄λ‘œμ €μΈμ²™ ν•΄μ•Όν•˜λŠ” 경우
func hasElement(in array: [Int], match predicate: (Int) -> Bool) -> Bool {
    return (array.lazy.filter { predicate($0) }.isEmpty == false)
}
  • μœ„μ˜ ν•¨μˆ˜μ—μ„œ match λΌλŠ” ν΄λ‘œμ €λŠ” λΉ„νƒˆμΆœ ν΄λ‘œμ €λ‘œ 전달이 λ˜μ—ˆμœΌλ‚˜,
  • ν•¨μˆ˜ λ‚΄μ—μ„œ lazy μ»¬λ ‰μ…˜μ„ μ‚¬μš© (비동기 μž‘μ—… μ‹œ μ‚¬μš©ν•˜λŠ” μ»¬λ ‰μ…˜) ν•˜λ―€λ‘œ,
  • filter λ©”μ„œλ“œκ°€ μš”κ΅¬ν•˜λŠ” ν΄λ‘œμ €λŠ” νƒˆμΆœ ν΄λ‘œμ €κ°€ λœλ‹€.
  • 어라라...?
  • withoutActuallyEscaping(_:do:) ν•¨μˆ˜λ₯Ό μ‚¬μš©ν•΄μ„œ ν•΄κ²°
func hasElement(in array: [Int], match predicate: (Int) -> Bool) -> Bool {
    return withoutActuallyEscaping(predicate, do: { escapablePredicate in
        array.lazy.filter { escapablePredicate($0) }.isEmpty == false)
    })
}

5. auto closure ⭐️

  • ν•¨μˆ˜μ— 인자둜 μ „λ‹¬λ˜λŠ” ν‘œν˜„μ‹μ„ λž˜ν•‘ν•˜κΈ° μœ„ν•΄ μžλ™μœΌλ‘œ μƒμ„±λ˜λŠ” ν΄λ‘œμ €
  • μΈμžκ°€ μ—†κ³ , λ°˜ν™˜κ°’λ§Œ μžˆλŠ” ν‘œν˜„μ‹μ„ μžλ™μœΌλ‘œ ν΄λ‘œμ €λ‘œ λ§Œλ“€μ–΄μ€€λ‹€.
  • κ°œλ°œν•˜λ©΄μ„œ 직접 κ΅¬ν˜„ν•  일은 λ§Žμ§€ μ•Šλ‹€.
  • πŸ“• μ½”λ“œκ°€ 맀우 μ–΄λ €μ›Œμ§€κΈ° λ•Œλ¬Έμ—.. 직접 κ΅¬ν˜„ν•˜κ²Œ λœλ‹€λ©΄ λ§€κ°œλ³€μˆ˜ 이름을 autoclosure μž„μ„ λ‚˜νƒ€λ‚Ό 수 μžˆλŠ” κ²ƒμœΌλ‘œ μ‚¬μš©ν•˜μž.

πŸ“• assert(condition:message:file:line:) μ—μ„œ condition, message κ°€ μžλ™ ν΄λ‘œμ €λ‘œ λ˜μ–΄ μžˆλ‹€.
πŸ“• ν΄λ‘œμ €μ— λŒ€ν•œ μ»¨λ²€μ…˜λ„ μ •ν•˜λŠ” 것이 μ’‹λ‹€.


μ•„λž˜μ²˜λŸΌ ν΄λ‘œμ €λ₯Ό λ°›μ•„μ„œ μ‹€ν–‰ν•˜λŠ” ν•¨μˆ˜μ—μ„œ 인자λ₯Ό 전달할 λ•ŒλŠ” {} 에 μ‹Έμ„œ 보내야 ν•œλ‹€. 당연함. ν΄λ‘œμ €μž„.

// customersInLine is ["Alex", "Ewa", "Barry", "Daniella"]
func serve(customer customerProvider: () -> String) {
    print("Now serving \(customerProvider())!")
}
serve(customer: { customersInLine.remove(at: 0) } )
// Prints "Now serving Alex!"
// customersInLine is ["Ewa", "Barry", "Daniella"]
func serve(customer customerProvider: @autoclosure () -> String) {
    print("Now serving \(customerProvider())!")
}
serve(customer: customersInLine.remove(at: 0))
// ν΄λ‘œμ € λŒ€μ‹  customerInLine.remove(at: 0) 의 κ²°κ³Ό κ°’ (String) 을 μ „λ‹¬λ°›κ²Œ λœλ‹€.
// Prints "Now serving Ewa!"
serve(customer: "hello")
// Prints "Now serving hello!"

auto closure μ΄λ©΄μ„œ escaping closure 일 μˆ˜λ„ μžˆλ‹€.

auto closure ν™œμš© μ˜ˆμ‹œλŠ” μ—¬κΈ°μ„œ μ°Έκ³ ν•˜λ©΄ 쒋을 λ“―!
https://jusung.github.io/AutoClosure/



질문

νƒˆμΆœ ν΄λ‘œμ €μ— λŒ€ν•˜μ—¬ μ„€λͺ…ν•˜μ‹œμ˜€.

νƒˆμΆœ ν΄λ‘œμ €λŠ” escaping closure λ‹€. closure λŠ” ν•¨μˆ˜μ˜ μΆ•μ•½ν˜•μ΄λΌκ³  보면 λ˜λŠ”λ°, ν•΄λ‹Ή ν΄λ‘œμ €κ°€ ν•¨μˆ˜ λ‚΄λΆ€μ—μ„œ 쓰이고 λλ‚˜μ§€ μ•Šκ³ , ν•¨μˆ˜ μ™ΈλΆ€μ—μ„œ μ“°μ΄λŠ” 경우! (특히, 비동기적인 μž‘μ—…μ„ ν•  λ•Œ ν•¨μˆ˜κ°€ λλ‚˜κ³ λ„ λ™μž‘ν•΄μ•Ό ν•˜λŠ” μ½”λ“œκ°€ μžˆλŠ” κ²½μš°μ— 쓰인닀.) ν•¨μˆ˜ μ™ΈλΆ€μ—μ„œ λ‚˜μ€‘μ— μ“°λŠ” ν΄λ‘œμ €μ΄λ‹€. 인자 라벨 μ•žμ— @escaping ν‚€μ›Œλ“œλ₯Ό μ¨μ„œ ν‘œμ‹œν•œλ‹€.

+) 0325 μΆ”κ°€μ μœΌλ‘œ μ°Ύμ•„ λ³Έ 것.

  • ν΄λ‘œμ €μ˜ 기본값은 non-escaping - 컴파일러의 μ½”λ“œλ₯Ό μ΅œμ ν™” κ³Όμ •μ—μ„œ μ„±λŠ₯ ν–₯상
  • self λ₯Ό 무쑰건 λͺ…μ‹œν•΄μ€˜μ•Ό ν•œλ‹€. -> λ©”λͺ¨λ¦¬ 관리λ₯Ό μœ„ν•΄ weak selfλ₯Ό 쓸지도 κ³ λ―Ό ν•„μš”.

+) 0401

  • 일단 Swift μ—μ„œλŠ” ν•¨μˆ˜λ₯Ό νƒ€μž…μœΌλ‘œ λ³Έλ‹€. κ·Έλž˜μ„œ ν•¨μˆ˜λ‚˜ ν΄λ‘œμ €λ₯Ό ν•¨μˆ˜μ˜ 인자둜 전달할 수 μžˆλŠ”λ°, ν΄λ‘œμ €λ₯Ό μ „λ‹¬ν•˜λŠ” 경우, ν•¨μˆ˜ μ•ˆμ—μ„œ ν΄λ‘œμ €κ°€ μ‹€ν–‰λ˜κ³  ν•¨μˆ˜κ°€ λλ‚˜λŠ”κ²Œ μΌλ°˜μ μ΄λ‹€. ν•˜μ§€λ§Œ, 비동기 μ‹€ν–‰ 같은 경우, ν•¨μˆ˜λŠ” λ¦¬ν„΄λμ§€λ§Œ ν΄λ‘œμ €λŠ” 계속 μ‹€ν–‰λ˜κ³  μžˆμ„ 수 μžˆλ‹€. (μ•„λ‹ˆλ©΄ ν•¨μˆ˜μ— ν•¨μˆ˜λ₯Ό μ „λ‹¬ν•΄μ„œ 배열에 넣어놓고 λ‚˜μ€‘μ— 배열에 μ ‘κ·Όν•΄μ„œ ν•¨μˆ˜λ₯Ό μ‚¬μš©ν•œλ‹€λ˜μ§€ ν•˜λŠ” 예제) 그러면 κ·Έ ν΄λ‘œμ €λŠ” ν•¨μˆ˜ λ°–μ—μ„œ 싀행이 될 μ˜ˆμ •μ΄κΈ° λ•Œλ¬Έμ—, @escaping 을 μ‚¬μš©ν•΄μ„œ ν΄λ‘œμ €κ°€ ν•¨μˆ˜ λ°–μ—μ„œ μ‚¬μš©λœλ‹€κ³  λͺ…μ‹œν•΄μ€€λ‹€.



μ°Έκ³ 

https://bbiguduk.gitbook.io/swift/language-guide-1/closures
https://github.com/JeaSungLEE/iOSInterviewquestions

profile
0λ…„μ°¨ iOS κ°œλ°œμžμž…λ‹ˆλ‹€.

0개의 λŒ“κΈ€