Closure basics
var multiplyClosure: (Int, Int) -> Int
multiplyClosure = { (a: Int, b: Int) -> Int in
return a * b
}
let result = multiplyClosure(4, 2)
Shorthand syntax
multiplyClosure = { (a: Int, b: Int) -> Int in
a * b
}
multiplyClosure = { (a, b) in
a * b
}
multiplyClosure = {
$0 * $1
}
Shorthand syntax
func operateOnNumbers(_ a: Int, _ b: Int, operation: (Int, Int) -> Int) -> Int {
let result = operation(a, b)
print(result)
return result
}
let addClosure = { (a: Int, b: Int) in
a + b
}
operateOnNumbers(4, 2, operation: addClosure)
func addFunction(_ a: Int, _ b: Int) -> Int {
return a + b
}
operateOnNumbers(4, 2, operation: addFunction)
operateOnNumbers(4, 2, operation: { (a: Int, b: Int) -> Int in
return a + b
})
operateOnNumbers(4, 2, operation: { $0 + $1 })
operateOnNumbers(4, 2, operation: +)
operateOnNumbers(4, 2) {
$0 + $1
}
Closures with no return value
let voidClosure: () -> Void = {
print("Swift Apprentice is awesome!")
}
voidClosure()
Note: Void is actually just a typealias for (). This means you could have written () -> Void as () -> (). A function’s parameter list however must always be surrounded by parentheses, so Void -> () or Void -> Void are invalid.
Capturing from the enclosing scope
var counter = 0
let incrementCounter = {
counter += 1
}
incrementCounter()
incrementCounter()
incrementCounter()
incrementCounter()
incrementCounter()
func countingClosure() -> () -> Int {
var counter = 0
let incrementCounter: () -> Int = {
counter += 1
return counter
}
return incrementCounter
}
let counter1 = countingClosure()
let counter2 = countingClosure()
counter1() // 1
counter2() // 1
counter1() // 2
counter1() // 3
counter2() // 2
Custom sorting with closures
let names = ["ZZZZZZ", "BB", "A", "CCCC", "EEEEE"]
names.sorted()
let sortedByLength = names.sorted {
$0.count > $1.count
}
sortedByLength
Iterating over collections with closures
let values = [1, 2, 3, 4, 5, 6]
values.forEach {
print("\($0): \($0*$0)")
}
var prices = [ 1.5, 10, 4.99, 2.30, 8.19]
let largePrices = prices.filter {
return $0 > 5
}
let salePrices = prices.map {
return $0 * 0.9
}
let userInput = ["0", "11", "haha", "42"]
let numbers1 = userInput.map {
Int($0)
}
let numbers2 = userInput.compactMap {
Int($0)
}
let sum = prices.reduce(0) {
return $0 + $1
}
let stock = [1.5: 5, 10: 2, 4.99: 20, 2.30: 5, 8.19: 30]
let stockSum = stock.reduce(0) {
return $0 + $1.key * Double($1.value)
}
let farmAnimals = ["🐎": 5, "🐄": 10, "🐑": 50, "🐶": 1]
let allAnimals = farmAnimals.reduce(into: []) {
(result, this: (key: String, value: Int)) in
for _ in 0 ..< this.value {
result.append(this.key)
}
}
let removeFirst = prices.dropFirst()
let removeFirstTwo = prices.dropFirst(2)
let removeLast = prices.dropLast()
let removeLastTwo = prices.dropLast(2)
let firstTwo = prices.prefix(2)
let lastTwo = prices.suffix(2)