Swift: Closure

Opublikowano: 07.09.2023 - tagi: Swift Funkcje

Czym jest Closure w Swift?

Closure w Swift to funkcja, która nie posiada nazwy.

let myFunction = {
	print("Hello!")
}

myFunction() // Hello!

Składnia Closure

Składnia prezentuje się następująco:

{ (parameters) -> returnType in
   ...
}

Tak jak w "zwykłej" funkcji, ta typu Closure może posiadać parametry i możesz określić zwracany typ danych.

let calculate = { (a: Int, b: Int) -> Int in
	return a + b
}

print(calculate(4, 3)) // 7

Zauważ, że w momencie wywołania funkcji typu Closure nie musimy podawać nazw parametrów, tak ja w "zwykłej" funkcji:

func substract(a: Int, b: Int) -> Int {
	return a - b
}

let add = { (a: Int, b: Int) -> Int in
	return a + b
}

print(add(4, 3)) // 7
print(substract(a: 10, b: 3)) // 7

print(substract(10, 3)) // błąd!

Closure jako parametr funkcji

Możesz przekazać do funkcji inną funkcję, która jest typu Closure:

let substract = { (a: Int, b: Int) -> Int in
	return a - b
}

let add = { (a: Int, b: Int) -> Int in
	return a + b
}

func calculate(a: Int, b: Int, operate: (_ a: Int, _ b: Int) -> (Int)) -> Int {
  return operate(a, b);
}

print(calculate(a: 5, b: 5, operate: add)) // 10
print(calculate(a: 5, b: 5, operate: substract)) // 0

Trailing Closure

Jeśli funkcja przyjmuje kilka parametrów i ostatnim z nich jest Closure można wywołać ją w inny sposób.

"Standardowa" wersja:

func calculate(a: Int, b: Int, operate: (_ a: Int, _ b: Int) -> (Int)) -> Int {
  return operate(a, b);
}

let result = calculate(a: 5, b: 5, operate: { (a: Int, b: Int) -> Int in
  return a + b
})

print(result) // 10

Można wywołać to też tak:

let result = calculate(a: 5, b: 5) { (a, b) in
  return a + b
}

print(result) // 10

Takie wywołanie nazwy się trailing closure.

Uproszczona składnia

Poniżej znajdziesz kilka sposobów wywołania Closure.

func calculate(a: Int, b: Int, operate: (_ a: Int, _ b: Int) -> (Int)) -> Int {
  return operate(a, b);
}

Przykłady wywołania Closure:

calculate(a: 5, b: 5, operate: { (a: Int, b: Int) -> Int in
  return a + b
})

Można krócej:

calculate(a: 5, b: 5) { (a, b) in
  return a + b
}

Inna wersja:

calculate(a: 5, b: 5) {
  a, b in a + b
}

Jeszcze prostsza wersja:

calculate(a: 5, b: 5) {
  $0 + $1
}

$0 i $1 to referencje do parametrów Closure.

Uwaga! Można jeszcze to zapisać jeszcze inaczej:

calculate(a: 5, b: 5, operate: +)