μ€λμ κ·Έλμ λ§μ΄ μ°μμ§λ§ κ·Έλ₯ μ§λμΉ closureμ λν΄ μμλ³΄κ³ μ νλ€.
μλ΅λ ννμ΄ λ§μμ μ΄κ² ν¨μμΈκ°? νκ³ μλ¬Έμ΄ λ€λλ λ§κ³ swift/IOS μ΄λ³΄ μΌλλ λ§μ΄ ν·κ°λ¦¬λ κ°λ μΈκ±° κ°λ€.
곡μ λ¬Έμ(swift-closure)μ ν¨κ» μ 리νλ€λ³΄λ©΄ μ΄μ μ μ©νκ² μ μ°κ² μ§ !!
Closureλ?
μ΅λͺ ν¨μ funcμΌλ‘ μ μΈνλ κ²μ΄ μλ ν¨μλ₯Ό λ³μμ μ μΈνλ νν
곡μ λ¬Έμμλ
ν΄λ‘μ λ μ΄λ€ μμλ λ³μμ μ°Έμ‘°λ₯Ό μΊ‘μ³(capture)ν΄ μ μ₯ν μ μλ€. λΌκ³ μ μν΄λμλ€. μ΄μ λν΄ μλμμ μμΈνκ² μ΄ν΄λ³΄μ
ν΄λ‘μ κ° κ°μ§λ ννλ λ€μκ³Ό κ°μ΄ 3κ°μ§λ€
μ μ ν¨μ : μ΄λ¦ O, μΊ‘μ³ X
μ€μ²© ν¨μ : μ΄λ¦ O, μΊ‘μ³ O
ν΄λ‘μ νν : μ΄λ¦ X, κ²½λνλ λ¬Έλ²μΌλ‘ κ΄λ ¨λ λ¬Έλ§₯(Context)λ‘λΆν° κ°μ μΊ‘μ³ O
ν΄λ‘μ ννμ κ°κ²°ν¨μ μΆκ΅¬νλ€! (κ·Έλμ μμ보기 μ΄λ €μ΄ κ±°μκ΅°)
μ΅μ νλ₯Ό μΆκ΅¬νλλ° μλμ κ°μ λΆλΆμ μμ΄μ ν¨μΆμ μΆκ΅¬νλ€
- λ¬Έλ§₯(context)μμ μΈμ νμ (parameter type)κ³Ό λ°ν νμ (return type)μ μΆλ‘
- λ¨μΌ νν ν΄λ‘μ μμμ μμμ λ°ν
- μΆμ½λ μΈμ μ΄λ¦
- νμ ν΄λ‘μ λ¬Έλ²
μ λ ¬ λ©μλ(Sorted Method)
swift νμ€ λΌμ΄λΈλ¬λ¦¬ sorted(by:)μ byλΆλΆμ μ΄λ€μμΌλ‘ μ λ ¬ν κ±΄μ§ κΈ°μ ν ν΄λ‘μ λ₯Ό λ£μΌλ©΄ κ·Έ λ°©λ²λλ‘ μ λ ¬λ λ°°μ΄μ μ»μ μ μλ€. μμλ‘ μ΄ν΄λ³΄μ
let names = ["Chris", "Alex", "Ewa", "Barry", "Daniella"]
ν΄λ‘μ λ₯Ό λ£λ μΌλ°μ μΈ λ°©λ²μ νλμ ν¨μλ₯Ό λ§λ€μ΄ λ£λκ²μ΄λ€.
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"]
backward ν¨μλ₯Ό λ§λ€κ³ sorted(by:) λΆλΆμ λ³μμ²λΌ backward ν¨μλ₯Ό λ£μ΄ μ£Όμλ€.
λ€μν ν΄λ‘μ λ€μ λν΄μλ μμ보기 μν΄ ν΄λ‘μ μ νν λ¬Έλ²μ λν΄ μ΄ν΄λ³΄λλ‘ νμ
{ (parameters) -> return type in
statements
}
μ΄κ²μ΄ ν΄λ‘μ μ νν λ¬Έλ²μ΄λ€!!
parameter(μΈμ)μ λν΄ μ²λ¦¬ν λΆλΆμ in λ€μ μλ statementμ λ£μ΄μ£Όκ³ statementμμ μ²λ¦¬λ₯Ό λλΈ λ€ returnνλ νμ μ λͺ μν΄μ€λ€. μ΄λ κ² ν¨μλ‘ λ°λ‘ μ μλ ννκ° μλ μΈμλ‘ λ€μ΄κ° μλ ννμ ν΄λ‘μ λ₯Ό μΈλΌμΈ ν΄λ‘μ λΌ λΆλ₯Έλ€.
μμ backwardν¨μλ λ€μκ³Ό κ°μ΄ μ°μΌ μλ μλ€.
reversedNames = names.sorted(by: { (s1: String, s2: String) -> Bool in
return s1 > s2
})
λ¬Έλ§₯μμ νμ μΆλ‘
μ¬κΈ°μλΆν° κΈ°λ³Ένμ λν μΆμ½μ΄ μΌμ΄λλ€. κΈ΄μ₯ν΄μΌ νλ€!
λ§μ½ sorted(by:)μμ μ΄λ―Έ (String, String) -> Bool νμ μ μΈμκ° λ€μ΄μμΌ νλμ§ μλ€λ©΄ ν΄λ‘μ μμ μ΄ νμ λ€μ μλ΅ λ μ μλ€.
reversedNames = names.sorted(by: { s1, s2 in return s1 > s2 } )
parameterμ returnμ νμ μ΄ μλ΅λκ±Έ νμΈ ν μ μλ€.
λ¨μΌ νν ν΄λ‘μ μμμ μμμ λ°ν
λ§μμ μ μ μλ―μ΄ μ΄λ²μλ λ°ν kewordκ° μλ΅ λ κ²μ΄λ€. returnμ μμΉκ° μ ν΄μ Έ μμΌλ―λ‘ μλ΅ν΄λ μ ν λͺ¨νΈν΄μ§μ§ μκΈ° λλ¬Έμ΄λ€.
reversedNames = names.sorted(by: { s1, s2 in s1 > s2 } )
μ΄λ¦ μΈμ μΆμ½
μ΄λ²μλ μΈμ μ΄λ¦μ μΆμ½ν΄λ³Ό κ²μ΄λ€.. μλ΅κΉμ§ μλκ³ μ΄λ¦λ§ κ°κ²°ν μ΄λ¦μΌλ‘ νννλ κ²μ΄λ€.
reversedNames = names.sorted(by: { $0 > $1 } )
$ ννκ³Ό ν¨κ» μ«μλ‘ νννλ€. μ λ² λ§μκ² μλ΅λμ΄μ λ μ€μΌ μ μμ κ±°λΌ μκ°ν κ²μ΄λ€.
νμ§λ§ νλ² λ μλ€ νν
μ°μ°μ λ©μλ
reversedNames = names.sorted(by: >)
λλ₯ .. γ· γ· γ·
λκ°μ΄ μκ°μ΄ λ§μ μ¬λλ€μ λ€μν ν΄μμ ν μλ μμ κ² κ°λ€λ μκ°μ΄ λ λ€. λ무 λ§μ μΆμ½κ³Ό μλ΅μ νμ κ³Ό μ½λ 리뷰μ μ μ’μ μλ μ’μ μλ μμΌλ 무μμ λ¨λ°μ μΌλ‘ μ¬μ©ν΄μ μλλ€
νμ ν΄λ‘μ Trailing Closures
λ§μ½ ν¨μμ λ§μ§λ§ μΈμλ‘ ν΄λ‘μ λ₯Ό λ£κ³ κ·Έ ν΄λ‘μ κ° κΈΈλ€λ©΄ νμ ν΄λ‘μ λ₯Ό μ¬μ©ν μ μλ€.
μμλ‘ μ΄ν΄λ³΄μ
func someFunctionThatTakesAClosure(closure: () -> Void) {
// function body goes here
}
λ§μ½ μ΄λ° ννμ ν΄λ‘μ κ° μλ€λ©΄ ν΄λ‘μ μ μΈμ κ° μ λ ₯ λΆλΆ ( () ) κ³Ό λ°νν λΆλΆ ( -> λ·λΆλΆ)μ μλ΅ν΄μ
someFunctionThatTakesAClosure(closure: {
// closure's body goes here
})
λλ
someFunctionThatTakesAClosure() { }
μ΄λ κ² μΈ μ μλ€.
μ°μ μ΄κ²λ ν΄λ‘μ μꡬλ ..!!! λλ° λλ°
λ€λ₯Έ μμ λ μ΄ν΄λ³΄μ
let digitNames = [
0: "Zero", 1: "One", 2: "Two", 3: "Three", 4: "Four",
5: "Five", 6: "Six", 7: "Seven", 8: "Eight", 9: "Nine"
]
let numbers = [16, 58, 510]
let strings = numbers.map { (number) -> String in
var number = number
var output = ""
repeat {
output = digitNames[number % 10]! + output
number /= 10
} while number > 0
return output
}
// let stringsλ νμ
μΆλ‘ μ μν΄ λ¬Έμ λ°°μ΄([String])νμ
μ κ°μ΅λλ€.
// κ²°κ³Όλ μ«μκ° λ¬Έμλ‘ λ°λ ["OneSix", "FiveEight", "FiveOneZero"]κ° λ©λλ€.
map ν¨μλ₯Ό μ¬μ©ν΄ κ° μ리μλ₯Ό ꡬν΄μ λ¬Έμλ‘ λ³ννκ³ 10μΌλ‘ λλ λ€ μ리μλ₯Ό λ°κΏ λ¬Έμλ‘ λ³ννλ κ²μ λ°λ³΅νλ€. numberλ μμμΈλ° ν΄λ‘μ μμμ varλ‘ μ¬μ μνκΈ° λλ¬Έμ κ°μ΄ λ³ν κ°λ₯νλ€.
κ° μΊ‘μ³ Capturing Values
ν΄λ‘μ λ νΉμ λ¬Έλ§₯μ μμλ λ³μμ κ°μ μΊ‘μ³ν μ μλ€.
λ€μλ§ν΄ μλ³Έ κ°μ΄ μ¬λΌμ Έλ ν΄λ‘μ Έμ bodyμμμ κ·Έ κ°μ νμ©ν μ μλ€λ κ².
Swiftμμ κ°μ μΊ‘μ³ νλ κ°μ₯ λ¨μν ννλ μ€μ²© ν¨μ(nested function) λ₯Ό μ¬μ©νλ κ²μΈλ° μμ λ‘ μ΄ν΄λ³΄μ
func makeIncrementer(forIncrement amount: Int) -> () -> Int {
var runningTotal = 0
func incrementer() -> Int {
runningTotal += amount
return runningTotal
}
return incrementer
}
makeIncrementer ν¨μ μ incrementer ν¨μκ° μ€μ²©λ ꡬ쑰λ€. μ΄λ ν΄λ‘μ κ° μ‘°κΈ μ κΈ°νκ² μκ²Όλ€.
(forIncrement amount: Int) -> () -> Int μ€μ μ²μ -> λ₯Ό κΈ°μ€μΌλ‘ μμ (forIncrement amount: Int) λΆλΆμ΄ μΈμ κ°μ΄κ³ λ€ () -> Intλ λ°ν κ°μ λλ€. --> (forIncrement amount: Int) -> ////// () -> Int μ΄λ κ² λμ΄ μ½μ΄μΌ νλ€. μ¦ λ°ν κ° λΆλΆμ΄ ν΄λ‘μ λ€!!
func incrementer() -> Int {
runningTotal += amount
return runningTotal
}
incrementer ν¨μλ§μ 보면 runningTotalμ amountκ° μΊ‘μ³λ§ λμλ€κ³ νννλ€.
makeIncrementer ν¨μ μ€ν μ () -> Int ν΄λ‘μ λ₯Ό λ°ννλλ° μ΄μ λν΄ incrementerν¨μκ° μ€νλκ³ κ·Έμ λν λ©μλλ₯Ό λ°ννλ€.
ν΄λ‘μ λ μ°Έμ‘°νμ μ΄λ―λ‘ ν¨μμ ν΄λ‘μ λ₯Ό μμλ λ³μμ ν λΉν λ μ€μ λ‘λ μμμ λ³μμ ν΄λΉ ν¨μλ ν΄λ‘μ μ μ°Έμ‘°(reference)κ° ν λΉλλ€. κ·Έλμ λ§μ½ ν ν΄λ‘μ λ₯Ό λ μμλ λ³μμ ν λΉνλ©΄ κ·Έ λ μμλ λ³μλ κ°μ ν΄λ‘μ λ₯Ό μ°Έμ‘°νκ² λλ€. ν¨μ ν¬μΈν°λ₯Ό μ μ₯νλ€κ³ μκ°νμλ©΄ μ΄ν΄νκΈ° μ¬μ°μ€ κ²!!
μ΄μ€μΌμ΄ν ν΄λ‘μ Escaping Closures
ν΄λ‘μ λ₯Ό ν¨μμ νλΌλ―Έν°λ‘ λ£μ μ μλλ°, ν¨μ λ°(ν¨μκ° λλκ³ )μμ μ€νλλ ν΄λ‘μ μλ₯Όλ€μ΄, λΉλκΈ°λ‘ μ€νλκ±°λ completionHandlerλ‘ μ¬μ©λλ ν΄λ‘μ λ νλΌλ―Έν° νμ μμ @escapingμ΄λΌλ ν€μλλ₯Ό λͺ μν΄μΌ νλ€.
var completionHandlers: [() -> Void] = []
func someFunctionWithEscapingClosure(completionHandler: @escaping () -> Void) {
completionHandlers.append(completionHandler)
}
μ ν¨μμμ μΈμλ‘ μ λ¬λ completionHandlerλ someFunctionWithEscapingClosure ν¨μκ° λλκ³ λμ€μ μ²λ¦¬ λλ€. λ§μ½ ν¨μκ° λλκ³ μ€νλλ ν΄λ‘μ μ @escaping ν€μλλ₯Ό λΆμ΄μ§ μμΌλ©΄ μ»΄νμΌμ μ€λ₯κ° λ°μν©λλ€.
@escaping λ₯Ό μ¬μ©νλ ν΄λ‘μ μμλ selfλ₯Ό λͺ μμ μΌλ‘ μΈκΈν΄μΌ ν©λλ€.
func someFunctionWithNonescapingClosure(closure: () -> Void) {
closure() // ν¨μ μμμ λλλ ν΄λ‘μ
}
class SomeClass {
var x = 10
func doSomething() {
someFunctionWithEscapingClosure { self.x = 100 } // λͺ
μμ μΌλ‘ selfλ₯Ό μ μ΄μ€μΌ ν©λλ€.
someFunctionWithNonescapingClosure { x = 200 }
}
}
let instance = SomeClass()
instance.doSomething()
print(instance.x)
// Prints "200"
completionHandlers.first?()
print(instance.x)
// Prints "100"
μλν΄λ‘μ Autoclosures
μλν΄λ‘μ λ μΈμ κ°μ΄ μμΌλ©° νΉμ ννμ κ°μΈμ λ€λ₯Έ ν¨μμ μ λ¬ μΈμλ‘ μ¬μ©ν μ μλ ν΄λ‘μ μ λλ€. μλν΄λ‘μ λ ν΄λ‘μ λ₯Ό μ€ννκΈ° μ κΉμ§ μ€μ μ€νμ΄ λμ§ μμ΅λλ€. κ·Έλμ κ³μ°μ΄ 볡μ‘ν μ°μ°μ νλλ° μ μ©ν©λλ€. μλλ©΄ μ€μ κ³μ°μ΄ νμν λ νΈμΆλκΈ° λλ¬Έμ λλ€. μμ λ₯Ό 보면μ λ¬΄μ¨ λ»μΈμ§ μμ λ³΄κ² μ΅λλ€.
var customersInLine = ["Chris", "Alex", "Ewa", "Barry", "Daniella"]
print(customersInLine.count)
// Prints "5"
let customerProvider = { customersInLine.remove(at: 0) }
print(customersInLine.count)
// Prints "5"
print("Now serving \(customerProvider())!")
// Prints "Now serving Chris!"
print(customersInLine.count)
// Prints "4"
μ μμ μ½λλ₯Ό 보면 let customerProvider = { customersInLine.remove(at: 0) } μ΄ ν΄λ‘μ μ½λλ₯Ό μ§λ¬μμλ λΆκ΅¬νκ³ customersInLine.count λ λ³ν¨μμ΄ 5μ΄λ€.
κ·Έλ¦¬κ³ κ·Έ ν΄λ‘μ λ₯Ό μ€νμν¨ print("Now serving \(customerProvider())!") μ΄νμμΌ λ°°μ΄μμ κ°μ΄ νλ μ κ±°λμ΄ λ°°μ΄μ μμ κ°μκ° 4λ‘ μ€μ΄λ λ€. μ΄λ λ― μλ ν΄λ‘μ λ μ νμ§ λΌμΈ μμλλ‘ λ°λ‘ μ€νλμ§ μκ³ , μ€μ μ¬μ©λ λ μ§μ° νΈμΆ λλ λ°©μμ΄λ€.
μλν΄λ‘μ λ₯Ό ν¨μμ μΈμ κ°μΌλ‘ λ£λ μμ λ μλμ κ°μ΅λλ€.
// 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!"
serveν¨μλ μΈμλ‘ () -> String) ν, μ¦ μΈμκ° μκ³ , Stringμ λ°ννλ ν΄λ‘μ λ₯Ό λ°λλ€.
μ μμ λ₯Ό @autoclosureν€μλλ₯Ό μ΄μ©ν΄μ λ³΄λ€ κ°κ²°νκ² μ¬μ©ν μ μμ κ²μ΄λ€.
μλ μμ λ₯Ό μ΄ν΄λ³΄μ
// customersInLine is ["Ewa", "Barry", "Daniella"]
func serve(customer customerProvider: @autoclosure () -> String) {
print("Now serving \(customerProvider())!")
}
serve(customer: customersInLine.remove(at: 0))
// Prints "Now serving Ewa!"
μ΄ ν€μλλ₯Ό λΆμμΌλ‘μ¨ μΈμ κ°μ μλμΌλ‘ ν΄λ‘μ λ‘ λ³νλλ€. ν¨μμ μΈμ κ°μ λ£μ λ ν΄λ‘μ κ° μλλΌ ν΄λ‘μ κ° λ°ννλ λ°ν κ°κ³Ό μΌμΉνλ νμ ν¨μλ₯Ό μΈμλ‘ λ£μ μ μλ€. κ·Έλμ serve(customer: { customersInLine.remove(at: 0) } ) μ΄λ° μ½λλ₯Ό @autoclosureν€μλλ₯Ό μ¬μ©νκΈ° λλ¬Έμ serve(customer: customersInLine.remove(at: 0)) μ΄λ κ² {} μμ΄ μ¬μ©ν μ μλ κ²μ΄λ€.
μ 리νλ©΄ ν΄λ‘μ μΈμμ @autoclosureλ₯Ό μ μΈνλ©΄ ν¨μκ° μ΄λ―Έ ν΄λ‘μ μΈκ²μ μκΈ° λλ¬Έμ 리ν΄κ° νμ κ³Ό κ°μ κ°μ λ£μ΄μ€ μ μμ΅λλ€.
ν΄λ‘μ λ μΆμ½νλ €λ νΉμ§ λλ¬Έμ λ€μν ννλ€μ κ°μ§λ κ²μ²λΌ 보μΈλ€. νλ νλ λ¨κ³μ μΌλ‘ μλ΅λμ΄ μ½λλ₯Ό 보μμΌ νμ§λ§ μ΄ λ¨κ³λ₯Ό μκ³ μλ€λ©΄ ν΄λ‘μ μμ νμ νκ³ λ¬΄μ¨ μλ―Έλ₯Ό λνλ΄λ κ²μΈμ§ νμ ν μ μμ κ²μ΄λ€!
μ΄μ μ 리 νμΌλκΉ closureλ λ§μ΄ μΉν΄μ§λλ‘ ππ
'IOSπ > iOS+Swift' μΉ΄ν κ³ λ¦¬μ λ€λ₯Έ κΈ
[iOS] Layout μ 리 (0) | 2021.04.27 |
---|---|
[iOS] UIScene, UIWindowScene, UISceneSession (0) | 2021.04.16 |
[iOS] Notificationκ³Ό NotificationCenter (0) | 2021.04.16 |
[Swift] Property - stored, computed, type / Observer (0) | 2021.04.13 |
[iOS] iOS13μ΄νμ AppDelegateμ SceneDelegate (0) | 2021.04.07 |
λκΈ