Introducció a les Closures

Les closures són blocs de funcionalitat que es poden passar i utilitzar en el teu codi. En Swift, les closures poden capturar i emmagatzemar referències a constants i variables del context en què es defineixen. Això es coneix com a captura de valors. Les closures en Swift són similars als blocs en C i Objective-C, així com als lambdas en altres llenguatges de programació.

Tipus de Closures

Hi ha tres tipus principals de closures en Swift:

  1. Funcions globals: Són closures que tenen un nom i no capturen cap valor.
  2. Funcions de nivell de funció: Són closures que tenen un nom i poden capturar valors de la seva funció de nivell superior.
  3. Expressions de closures: Són closures sense nom que utilitzen una sintaxi lleugera i poden capturar valors del seu context.

Sintaxi de les Closures

La sintaxi bàsica d'una closure és la següent:

{ (parameters) -> returnType in
    // codi de la closure
}

Exemple Bàsic

let salutacio = { (nom: String) -> String in
    return "Hola, \(nom)!"
}

let missatge = salutacio("Anna")
print(missatge) // Sortida: Hola, Anna!

Closures com a Paràmetres de Funció

Les closures es poden passar com a arguments a les funcions. Això és especialment útil per a funcions d'ordre superior, que són funcions que prenen altres funcions com a arguments o que retornen una funció com a resultat.

Exemple amb Funció d'Ordre Superior

func repeteixTresVegades(operacio: () -> Void) {
    for _ in 1...3 {
        operacio()
    }
}

repeteixTresVegades {
    print("Això és una closure!")
}
// Sortida:
// Això és una closure!
// Això és una closure!
// Això és una closure!

Captura de Valors

Les closures poden capturar constants i variables del seu context. Swift gestiona la captura de valors de manera automàtica.

Exemple de Captura de Valors

func creaIncrementador(increment: Int) -> () -> Int {
    var total = 0
    let incrementador: () -> Int = {
        total += increment
        return total
    }
    return incrementador
}

let incrementaDeCinc = creaIncrementador(increment: 5)
print(incrementaDeCinc()) // Sortida: 5
print(incrementaDeCinc()) // Sortida: 10

Closures i Tipus de Referència

Les closures són tipus de referència, el que significa que quan assignes una closure a una variable o constant, estàs assignant una referència a aquesta closure, no una còpia.

Exemple de Tipus de Referència

let incrementaDeDeu = creaIncrementador(increment: 10)
let unaAltraReferència = incrementaDeDeu

print(unaAltraReferència()) // Sortida: 10
print(incrementaDeDeu())    // Sortida: 20

Exercicis Pràctics

Exercici 1: Crear una Closure Simple

Crea una closure que prengui dos enters com a paràmetres i retorni la seva suma.

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

print(suma(3, 5)) // Sortida: 8

Exercici 2: Utilitzar una Closure com a Paràmetre

Escriu una funció que prengui una closure com a paràmetre i la cridi tres vegades.

func cridaTresVegades(closure: () -> Void) {
    for _ in 1...3 {
        closure()
    }
}

cridaTresVegades {
    print("Closure cridada!")
}
// Sortida:
// Closure cridada!
// Closure cridada!
// Closure cridada!

Exercici 3: Captura de Valors

Crea una funció que retorni una closure que incrementi un valor capturat.

func creaContador() -> () -> Int {
    var comptador = 0
    return {
        comptador += 1
        return comptador
    }
}

let contador = creaContador()
print(contador()) // Sortida: 1
print(contador()) // Sortida: 2

Errors Comuns i Consells

  • Oblidar el in: Quan defineixes una closure, assegura't d'incloure la paraula clau in per separar els paràmetres i el tipus de retorn del cos de la closure.
  • Captura de valors inesperada: Tingues en compte que les closures poden capturar valors del seu context. Això pot portar a comportaments inesperats si no es gestiona correctament.
  • Retenció cíclica: Les closures poden causar retencions cíclics si capturen referències fortes a objectes que també tenen una referència forta a la closure. Utilitza weak o unowned per evitar-ho.

Conclusió

Les closures són una eina poderosa en Swift que permeten escriure codi més flexible i reutilitzable. Comprendre com definir, utilitzar i gestionar closures és essencial per a qualsevol desenvolupador de Swift. Amb la pràctica, les closures es convertiran en una part natural del teu repertori de programació.

© Copyright 2024. Tots els drets reservats