> For the complete documentation index, see [llms.txt](https://swift.unicorndonkeys.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://swift.unicorndonkeys.com/guida-al-linguaggio/flusso-di-controllo.md).

# Flusso di controllo (Control Flow)

Struttura il codice con diramazioni, cicli e uscite anticipate.

Swift fornisce una varietà di istruzioni di controllo del flusso. Queste comprendono i cicli `while` per eseguire un compito più volte; le istruzioni `if`, `guard` e `switch` per eseguire diversi rami di codice in base a determinate condizioni; e istruzioni come `break` e `continue` per trasferire il flusso di esecuzione a un altro punto del tuo codice. Swift fornisce un ciclo `for`-`in` che rende facile iterare su array, dizionari, intervalli, stringhe e altre sequenze. Swift fornisce anche le istruzioni `defer`, che racchiudono codice da eseguire quando si esce dall'ambito corrente.

L'istruzione `switch` di Swift è considerevolmente più potente della sua controparte in molti linguaggi simili al C. I casi possono corrispondere a molti pattern diversi, comprese corrispondenze con intervalli, tuple e conversioni a un tipo specifico. I valori corrispondenti in un caso di `switch` possono essere associati a costanti o variabili temporanee da usare all'interno del corpo del caso, e condizioni di corrispondenza complesse possono essere espresse con una clausola `where` per ciascun caso.

## Cicli for-in <a href="#cicli-for-in" id="cicli-for-in"></a>

Usi il ciclo `for`-`in` per iterare su una sequenza, come gli elementi di un array, gli intervalli di numeri o i caratteri di una stringa.

Questo esempio usa un ciclo `for`-`in` per iterare sugli elementi di un array:

```swift
let names = ["Anna", "Alex", "Brian", "Jack"]
for name in names {
    print("Hello, \(name)!")
}
// Hello, Anna!
// Hello, Alex!
// Hello, Brian!
// Hello, Jack!
```

Puoi anche iterare su un dizionario per accedere alle sue coppie chiave-valore. Ogni elemento del dizionario viene restituito come tupla `(key, value)` quando si itera sul dizionario, e puoi scomporre i membri della tupla `(key, value)` in costanti con nomi espliciti da usare all'interno del corpo del ciclo `for`-`in`. Nell'esempio di codice seguente, le chiavi del dizionario vengono scomposte in una costante chiamata `animalName`, e i valori del dizionario vengono scomposti in una costante chiamata `legCount`.

```swift
let numberOfLegs = ["spider": 8, "ant": 6, "cat": 4]
for (animalName, legCount) in numberOfLegs {
    print("\(animalName)s have \(legCount) legs")
}
// cats have 4 legs
// ants have 6 legs
// spiders have 8 legs
```

Il contenuto di un `Dictionary` è intrinsecamente non ordinato, e iterare su di esso non garantisce l'ordine in cui gli elementi verranno recuperati. In particolare, l'ordine in cui inserisci gli elementi in un `Dictionary` non definisce l'ordine in cui vengono iterati. Per saperne di più su array e dizionari, vedi [Tipi collezione](/guida-al-linguaggio/tipi-collezione.md).

Puoi usare i cicli `for`-`in` anche con gli intervalli numerici. Questo esempio stampa le prime voci della tabellina del cinque:

```swift
for index in 1...5 {
    print("\(index) times 5 is \(index * 5)")
}
// 1 times 5 is 5
// 2 times 5 is 10
// 3 times 5 is 15
// 4 times 5 is 20
// 5 times 5 is 25
```

La sequenza su cui si itera è un intervallo di numeri da `1` a `5`, inclusi, come indicato dall'uso dell'operatore di intervallo chiuso (`...`). Il valore di `index` viene impostato al primo numero dell'intervallo (`1`), e vengono eseguite le istruzioni all'interno del ciclo. In questo caso, il ciclo contiene una sola istruzione, che stampa una voce della tabellina del cinque per il valore corrente di `index`. Dopo l'esecuzione dell'istruzione, il valore di `index` viene aggiornato per contenere il secondo valore dell'intervallo (`2`), e la funzione `print(_:separator:terminator:)` viene chiamata di nuovo. Questo processo continua finché non si raggiunge la fine dell'intervallo.

Nell'esempio qui sopra, `index` è una costante il cui valore viene impostato automaticamente all'inizio di ogni iterazione del ciclo. Di conseguenza, `index` non deve essere dichiarata prima di essere usata. Viene dichiarata implicitamente semplicemente includendola nella dichiarazione del ciclo, senza bisogno di una parola chiave di dichiarazione `let`.

Se non ti serve ciascun valore di una sequenza, puoi ignorare i valori usando un trattino basso al posto del nome di una variabile.

```swift
let base = 3
let power = 10
var answer = 1
for _ in 1...power {
    answer *= base
}
print("\(base) to the power of \(power) is \(answer)")
// Stampa "3 to the power of 10 is 59049".
```

L'esempio qui sopra calcola il valore di un numero elevato alla potenza di un altro (in questo caso, `3` elevato alla potenza di `10`). Moltiplica un valore iniziale di `1` (cioè `3` elevato alla potenza di `0`) per `3`, dieci volte, usando un intervallo chiuso che inizia con `1` e termina con `10`. Per questo calcolo, i singoli valori del contatore a ogni passaggio del ciclo non sono necessari — il codice si limita a eseguire il ciclo il numero corretto di volte. Il carattere trattino basso (`_`) usato al posto di una variabile del ciclo fa sì che i singoli valori vengano ignorati e non fornisce accesso al valore corrente durante ciascuna iterazione del ciclo.

In alcune situazioni, potresti non voler usare gli intervalli chiusi, che includono entrambi gli estremi. Considera il disegno delle tacche per ogni minuto sul quadrante di un orologio. Vuoi disegnare `60` tacche, a partire dal minuto `0`. Usa l'operatore di intervallo semiaperto (`..<`) per includere il limite inferiore ma non quello superiore. Per saperne di più sugli intervalli, vedi [Operatori di intervallo](/guida-al-linguaggio/operatori-di-base.md#operatori-di-intervallo).

```swift
let minutes = 60
for tickMark in 0..<minutes {
    // disegna la tacca di ogni minuto (60 volte)
}
```

Alcuni utenti potrebbero volere meno tacche nella loro interfaccia utente. Potrebbero preferire una tacca ogni `5` minuti. Usa la funzione `stride(from:to:by:)` per saltare le tacche indesiderate.

```swift
let minuteInterval = 5
for tickMark in stride(from: 0, to: minutes, by: minuteInterval) {
    // disegna la tacca ogni 5 minuti (0, 5, 10, 15 ... 45, 50, 55)
}
```

Sono disponibili anche gli intervalli chiusi, usando invece `stride(from:through:by:)`:

```swift
let hours = 12
let hourInterval = 3
for tickMark in stride(from: 3, through: hours, by: hourInterval) {
    // disegna la tacca ogni 3 ore (3, 6, 9, 12)
}
```

Gli esempi qui sopra usano un ciclo `for`-`in` per iterare su intervalli, array, dizionari e stringhe. Tuttavia, puoi usare questa sintassi per iterare su *qualsiasi* collezione, comprese le tue classi e i tuoi tipi collezione, purché quei tipi siano conformi al protocollo [`Sequence`](https://developer.apple.com/documentation/swift/sequence).

## Cicli while <a href="#cicli-while" id="cicli-while"></a>

Un ciclo `while` esegue un insieme di istruzioni finché una condizione non diventa `false`. Questo tipo di cicli è più indicato quando il numero di iterazioni non è noto prima dell'inizio della prima iterazione. Swift fornisce due tipi di cicli `while`:

* `while` valuta la sua condizione all'inizio di ogni passaggio del ciclo.
* `repeat`-`while` valuta la sua condizione alla fine di ogni passaggio del ciclo.

### While <a href="#while" id="while"></a>

Un ciclo `while` inizia valutando una singola condizione. Se la condizione è `true`, un insieme di istruzioni viene ripetuto finché la condizione non diventa `false`.

Ecco la forma generale di un ciclo `while`:

```swift
while <#condition#> {
   <#statements#>
}
```

Questo esempio gioca una semplice partita a *Serpenti e scale* (noto anche come *Chutes and Ladders*):

![](https://3581893755-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FNzatREGwodw9Z93LQYJb%2Fuploads%2F4TKFWiSgohkE4yTOxUAU%2FsnakesAndLadders%402x.png?alt=media)

Le regole del gioco sono le seguenti:

* Il tabellone ha 25 caselle, e l'obiettivo è arrivare sulla casella 25 o oltre.
* La casella di partenza del giocatore è la “casella zero”, che si trova appena fuori dall'angolo in basso a sinistra del tabellone.
* A ogni turno, lanci un dado a sei facce e ti sposti di quel numero di caselle, seguendo il percorso orizzontale indicato dalla freccia tratteggiata qui sopra.
* Se il tuo turno termina alla base di una scala, sali lungo quella scala.
* Se il tuo turno termina sulla testa di un serpente, scendi lungo quel serpente.

Il tabellone di gioco è rappresentato da un array di valori `Int`. La sua dimensione si basa su una costante chiamata `finalSquare`, che viene usata per inizializzare l'array e anche per verificare la condizione di vittoria più avanti nell'esempio. Poiché i giocatori partono fuori dal tabellone, sulla "casella zero", il tabellone viene inizializzato con 26 valori `Int` pari a zero, non 25.

```swift
let finalSquare = 25
var board = [Int](repeating: 0, count: finalSquare + 1)
```

Ad alcune caselle vengono poi assegnati valori più specifici per i serpenti e le scale. Le caselle con la base di una scala hanno un numero positivo per farti salire sul tabellone, mentre le caselle con la testa di un serpente hanno un numero negativo per farti scendere sul tabellone.

```swift
board[03] = +08; board[06] = +11; board[09] = +09; board[10] = +02
board[14] = -10; board[19] = -11; board[22] = -02; board[24] = -08
```

La casella 3 contiene la base di una scala che ti fa salire alla casella 11. Per rappresentarlo, `board[03]` è uguale a `+08`, che equivale a un valore intero di `8` (la differenza tra `3` e `11`). Per allineare i valori e le istruzioni, l'operatore più unario (`+i`) viene usato esplicitamente insieme all'operatore meno unario (`-i`) e i numeri inferiori a `10` sono completati con degli zeri. (Nessuna delle due tecniche stilistiche è strettamente necessaria, ma portano a un codice più ordinato.)

```swift
var square = 0
var diceRoll = 0
while square < finalSquare {
    // lancia il dado
    diceRoll += 1
    if diceRoll == 7 { diceRoll = 1 }
    // spostati del numero ottenuto
    square += diceRoll
    if square < board.count {
        // se siamo ancora sul tabellone, sali o scendi per una scala o un serpente
        square += board[square]
    }
}
print("Game over!")
```

L'esempio qui sopra usa un approccio molto semplice al lancio del dado. Invece di generare un numero casuale, inizia con un valore di `diceRoll` pari a `0`. A ogni passaggio del ciclo `while`, `diceRoll` viene incrementato di uno e poi si verifica se è diventato troppo grande. Ogni volta che questo valore di ritorno è uguale a `7`, il lancio del dado è diventato troppo grande e viene riportato al valore `1`. Il risultato è una sequenza di valori di `diceRoll` che è sempre `1`, `2`, `3`, `4`, `5`, `6`, `1`, `2` e così via.

Dopo il lancio del dado, il giocatore avanza di `diceRoll` caselle. È possibile che il lancio del dado abbia fatto avanzare il giocatore oltre la casella 25, nel qual caso la partita è finita. Per gestire questo scenario, il codice verifica che `square` sia minore della proprietà `count` dell'array `board`. Se `square` è valido, il valore memorizzato in `board[square]` viene aggiunto al valore corrente di `square` per far salire o scendere il giocatore lungo eventuali scale o serpenti.

{% hint style="info" %}
**Nota:** Se questa verifica non venisse eseguita, `board[square]` potrebbe tentare di accedere a un valore al di fuori dei limiti dell'array `board`, il che attiverebbe un errore in fase di esecuzione.
{% endhint %}

L'esecuzione corrente del ciclo `while` termina quindi, e la condizione del ciclo viene verificata per vedere se il ciclo deve essere eseguito di nuovo. Se il giocatore è arrivato sulla casella numero `25` o oltre, la condizione del ciclo restituisce `false` e la partita termina.

In questo caso è appropriato un ciclo `while`, perché la durata della partita non è chiara all'inizio del ciclo `while`. Il ciclo viene invece eseguito finché non è soddisfatta una particolare condizione.

### Repeat-while <a href="#repeat-while" id="repeat-while"></a>

L'altra variante del ciclo `while`, nota come ciclo `repeat`-`while`, esegue prima un singolo passaggio nel blocco del ciclo, *prima* di considerare la condizione del ciclo. Poi continua a ripetere il ciclo finché la condizione non è `false`.

{% hint style="info" %}
**Nota:** Il ciclo `repeat`-`while` in Swift è analogo a un ciclo `do`-`while` in altri linguaggi.
{% endhint %}

Ecco la forma generale di un ciclo `repeat`-`while`:

```swift
repeat {
   <#statements#>
} while <#condition#>
```

Ecco di nuovo l'esempio di *Serpenti e scale*, scritto come ciclo `repeat`-`while` anziché come ciclo `while`. I valori di `finalSquare`, `board`, `square` e `diceRoll` vengono inizializzati esattamente nello stesso modo del ciclo `while`.

```swift
let finalSquare = 25
var board = [Int](repeating: 0, count: finalSquare + 1)
board[03] = +08; board[06] = +11; board[09] = +09; board[10] = +02
board[14] = -10; board[19] = -11; board[22] = -02; board[24] = -08
var square = 0
var diceRoll = 0
```

In questa versione del gioco, la *prima* azione del ciclo è verificare la presenza di una scala o di un serpente. Nessuna scala del tabellone porta il giocatore direttamente alla casella 25, e quindi non è possibile vincere la partita salendo su una scala. Pertanto, è sicuro verificare la presenza di un serpente o di una scala come prima azione del ciclo.

All'inizio della partita, il giocatore si trova sulla “casella zero”. `board[0]` è sempre uguale a `0` e non ha alcun effetto.

```swift
repeat {
    // sali o scendi per una scala o un serpente
    square += board[square]
    // lancia il dado
    diceRoll += 1
    if diceRoll == 7 { diceRoll = 1 }
    // spostati del numero ottenuto
    square += diceRoll
} while square < finalSquare
print("Game over!")
```

Dopo che il codice ha verificato la presenza di serpenti e scale, viene lanciato il dado e il giocatore avanza di `diceRoll` caselle. L'esecuzione corrente del ciclo termina quindi.

La condizione del ciclo (`while square < finalSquare`) è la stessa di prima, ma questa volta non viene valutata fino alla *fine* del primo passaggio del ciclo. La struttura del ciclo `repeat`-`while` è più adatta a questo gioco rispetto al ciclo `while` dell'esempio precedente. Nel ciclo `repeat`-`while` qui sopra, `square += board[square]` viene sempre eseguito *immediatamente dopo* che la condizione `while` del ciclo ha confermato che `square` si trova ancora sul tabellone. Questo comportamento elimina la necessità del controllo dei limiti dell'array visto nella versione del gioco con il ciclo `while` descritta in precedenza.

## Istruzioni condizionali <a href="#istruzioni-condizionali" id="istruzioni-condizionali"></a>

È spesso utile eseguire porzioni di codice diverse in base a determinate condizioni. Potresti voler eseguire una porzione di codice aggiuntiva quando si verifica un errore, o mostrare un messaggio quando un valore diventa troppo alto o troppo basso. Per farlo, rendi *condizionali* alcune parti del tuo codice.

Swift fornisce due modi per aggiungere rami condizionali al tuo codice: l'istruzione `if` e l'istruzione `switch`. Di solito, usi l'istruzione `if` per valutare condizioni semplici con pochi esiti possibili. L'istruzione `switch` è più adatta a condizioni più complesse con molteplici combinazioni possibili ed è utile nelle situazioni in cui il pattern matching può aiutare a selezionare un ramo di codice appropriato da eseguire.

### If <a href="#if" id="if"></a>

Nella sua forma più semplice, l'istruzione `if` ha un'unica condizione `if`. Esegue un insieme di istruzioni solo se quella condizione è `true`.

```swift
var temperatureInFahrenheit = 30
if temperatureInFahrenheit <= 32 {
    print("It's very cold. Consider wearing a scarf.")
}
// Stampa "It's very cold. Consider wearing a scarf."
```

L'esempio qui sopra verifica se la temperatura è minore o uguale a 32 gradi Fahrenheit (il punto di congelamento dell'acqua). Se lo è, viene stampato un messaggio. Altrimenti, non viene stampato alcun messaggio, e l'esecuzione del codice prosegue dopo la parentesi graffa di chiusura dell'istruzione `if`.

L'istruzione `if` può fornire un insieme alternativo di istruzioni, noto come *clausola else*, per le situazioni in cui la condizione `if` è `false`. Queste istruzioni sono indicate dalla parola chiave `else`.

```swift
temperatureInFahrenheit = 40
if temperatureInFahrenheit <= 32 {
    print("It's very cold. Consider wearing a scarf.")
} else {
    print("It's not that cold. Wear a T-shirt.")
}
// Stampa "It's not that cold. Wear a T-shirt."
```

Uno di questi due rami viene sempre eseguito. Poiché la temperatura è salita a `40` gradi Fahrenheit, non fa più abbastanza freddo da consigliare di indossare una sciarpa, e quindi viene invece attivato il ramo `else`.

Puoi concatenare più istruzioni `if` per considerare clausole aggiuntive.

```swift
temperatureInFahrenheit = 90
if temperatureInFahrenheit <= 32 {
    print("It's very cold. Consider wearing a scarf.")
} else if temperatureInFahrenheit >= 86 {
    print("It's really warm. Don't forget to wear sunscreen.")
} else {
    print("It's not that cold. Wear a T-shirt.")
}
// Stampa "It's really warm. Don't forget to wear sunscreen."
```

Qui, è stata aggiunta un'ulteriore istruzione `if` per rispondere a temperature particolarmente calde. La clausola `else` finale rimane, e stampa una risposta per tutte le temperature che non sono né troppo calde né troppo fredde.

La clausola `else` finale, tuttavia, è opzionale, e può essere esclusa se l'insieme delle condizioni non deve essere completo.

```swift
temperatureInFahrenheit = 72
if temperatureInFahrenheit <= 32 {
    print("It's very cold. Consider wearing a scarf.")
} else if temperatureInFahrenheit >= 86 {
    print("It's really warm. Don't forget to wear sunscreen.")
}
```

Poiché la temperatura non è abbastanza fredda da attivare la condizione `if` né abbastanza calda da attivare la condizione `else if`, non viene stampato alcun messaggio.

Swift fornisce una forma abbreviata di `if` che puoi usare quando imposti dei valori. Per esempio, considera il codice seguente:

```swift
let temperatureInCelsius = 25
let weatherAdvice: String

if temperatureInCelsius <= 0 {
    weatherAdvice = "It's very cold. Consider wearing a scarf."
} else if temperatureInCelsius >= 30 {
    weatherAdvice = "It's really warm. Don't forget to wear sunscreen."
} else {
    weatherAdvice = "It's not that cold. Wear a T-shirt."
}

print(weatherAdvice)
// Stampa "It's not that cold. Wear a T-shirt."
```

Qui, ciascuno dei rami imposta un valore per la costante `weatherAdvice`, che viene stampata dopo l'istruzione `if`.

Usando la sintassi alternativa, nota come espressione `if`, puoi scrivere questo codice in modo più conciso:

```swift
let weatherAdvice = if temperatureInCelsius <= 0 {
    "It's very cold. Consider wearing a scarf."
} else if temperatureInCelsius >= 30 {
    "It's really warm. Don't forget to wear sunscreen."
} else {
    "It's not that cold. Wear a T-shirt."
}

print(weatherAdvice)
// Stampa "It's not that cold. Wear a T-shirt."
```

In questa versione con l'espressione `if`, ogni ramo contiene un singolo valore. Se la condizione di un ramo è vera, allora il valore di quel ramo viene usato come valore dell'intera espressione `if` nell'assegnamento di `weatherAdvice`. Ogni ramo `if` ha un corrispondente ramo `else if` o `else`, il che garantisce che uno dei rami corrisponda sempre e che l'espressione `if` produca sempre un valore, indipendentemente da quali condizioni siano vere.

Poiché la sintassi dell'assegnamento inizia al di fuori dell'espressione `if`, non c'è bisogno di ripetere `weatherAdvice =` all'interno di ciascun ramo. Invece, ogni ramo dell'espressione `if` produce uno dei tre possibili valori di `weatherAdvice`, e l'assegnamento usa quel valore.

Tutti i rami di un'espressione `if` devono contenere valori dello stesso tipo. Poiché Swift verifica il tipo di ciascun ramo separatamente, valori come `nil`, che possono essere usati con più di un tipo, impediscono a Swift di determinare automaticamente il tipo dell'espressione `if`. Devi invece specificare esplicitamente il tipo — per esempio:

```swift
let freezeWarning: String? = if temperatureInCelsius <= 0 {
    "It's below freezing. Watch for ice!"
} else {
    nil
}
```

Nel codice qui sopra, un ramo dell'espressione `if` ha un valore stringa e l'altro ramo ha un valore `nil`. Il valore `nil` potrebbe essere usato come valore per qualsiasi tipo opzionale, quindi devi scrivere esplicitamente che `freezeWarning` è una stringa opzionale, come descritto in [Annotazioni di tipo](/guida-al-linguaggio/le-basi.md#annotazioni-di-tipo).

Un modo alternativo per fornire questa informazione di tipo è fornire un tipo esplicito per `nil`, invece di fornire un tipo esplicito per `freezeWarning`:

```swift
let freezeWarning = if temperatureInCelsius <= 0 {
    "It's below freezing. Watch for ice!"
} else {
    nil as String?
}
```

Un'espressione `if` può rispondere a fallimenti inattesi lanciando un errore o chiamando una funzione che non restituisce mai, come `fatalError(_:file:line:)`. Per esempio:

```swift
let weatherAdvice = if temperatureInCelsius > 100 {
    throw TemperatureError.boiling
} else {
    "It's a reasonable temperature."
}
```

In questo esempio, l'espressione `if` verifica se la temperatura prevista è superiore a 100° C — il punto di ebollizione dell'acqua. Una temperatura così alta fa sì che l'espressione `if` lanci un errore `.boiling` invece di restituire un riepilogo testuale. Anche se questa espressione `if` può lanciare un errore, non scrivi `try` prima di essa. Per informazioni su come lavorare con gli errori, vedi [Gestione degli errori](/guida-al-linguaggio/gestione-degli-errori.md).

Oltre a usare le espressioni `if` sul lato destro di un assegnamento, come mostrato negli esempi qui sopra, puoi anche usarle come valore restituito da una funzione o da una closure.

### Switch <a href="#switch" id="switch"></a>

Un'istruzione `switch` considera un valore e lo confronta con diversi possibili pattern di corrispondenza. Poi esegue un blocco di codice appropriato, in base al primo pattern che trova corrispondenza con successo. Un'istruzione `switch` fornisce un'alternativa all'istruzione `if` per rispondere a più stati possibili.

Nella sua forma più semplice, un'istruzione `switch` confronta un valore con uno o più valori dello stesso tipo.

```swift
switch <#some value to consider#> {
case <#value 1#>:
    <#respond to value 1#>
case <#value 2#>,
    <#value 3#>:
    <#respond to value 2 or 3#>
default:
    <#otherwise, do something else#>
}
```

Ogni istruzione `switch` è costituita da più *casi* possibili, ciascuno dei quali inizia con la parola chiave `case`. Oltre al confronto con valori specifici, Swift fornisce diversi modi per ciascun caso di specificare pattern di corrispondenza più complessi. Queste opzioni sono descritte più avanti in questo capitolo.

Come il corpo di un'istruzione `if`, ogni `case` è un ramo separato di esecuzione del codice. L'istruzione `switch` determina quale ramo debba essere selezionato. Questa procedura è nota come *switching* (commutazione) sul valore considerato.

Ogni istruzione `switch` deve essere *esaustiva*. Cioè, ogni possibile valore del tipo considerato deve trovare corrispondenza in uno dei casi dello `switch`. Se non è appropriato fornire un caso per ogni possibile valore, puoi definire un caso predefinito per coprire tutti i valori non trattati esplicitamente. Questo caso predefinito è indicato dalla parola chiave `default`, e deve comparire sempre per ultimo.

Questo esempio usa un'istruzione `switch` per considerare un singolo carattere minuscolo chiamato `someCharacter`:

```swift
let someCharacter: Character = "z"
switch someCharacter {
case "a":
    print("The first letter of the Latin alphabet")
case "z":
    print("The last letter of the Latin alphabet")
default:
    print("Some other character")
}
// Stampa "The last letter of the Latin alphabet".
```

Il primo caso dell'istruzione `switch` corrisponde alla prima lettera dell'alfabeto inglese, `a`, e il suo secondo caso corrisponde all'ultima lettera, `z`. Poiché lo `switch` deve avere un caso per ogni possibile carattere, non solo per ogni carattere alfabetico, questa istruzione `switch` usa un caso `default` per corrispondere a tutti i caratteri diversi da `a` e `z`. Questo accorgimento garantisce che l'istruzione `switch` sia esaustiva.

Come le istruzioni `if`, anche le istruzioni `switch` hanno una forma di espressione:

```swift
let anotherCharacter: Character = "a"
let message = switch anotherCharacter {
case "a":
    "The first letter of the Latin alphabet"
case "z":
    "The last letter of the Latin alphabet"
default:
    "Some other character"
}

print(message)
// Stampa "The first letter of the Latin alphabet".
```

In questo esempio, ogni caso dell'espressione `switch` contiene il valore di `message` da usare quando quel caso corrisponde ad `anotherCharacter`. Poiché `switch` è sempre esaustivo, c'è sempre un valore da assegnare.

Come per le espressioni `if`, puoi lanciare un errore o chiamare una funzione che non restituisce mai, come `fatalError(_:file:line:)`, invece di fornire un valore per un dato caso. Puoi usare le espressioni `switch` sul lato destro di un assegnamento, come mostrato nell'esempio qui sopra, e come valore restituito da una funzione o da una closure.

#### Nessun fallthrough implicito <a href="#nessun-fallthrough-implicito" id="nessun-fallthrough-implicito"></a>

A differenza delle istruzioni `switch` in C e Objective-C, le istruzioni `switch` in Swift per impostazione predefinita non proseguono (fall through) dal fondo di ciascun caso al caso successivo. Invece, l'intera istruzione `switch` termina la sua esecuzione non appena il primo caso `switch` corrispondente è completato, senza richiedere un'istruzione `break` esplicita. Questo rende l'istruzione `switch` più sicura e più facile da usare di quella del C ed evita di eseguire per errore più di un caso `switch`.

{% hint style="info" %}
**Nota:** Sebbene in Swift `break` non sia obbligatorio, puoi usare un'istruzione `break` per trovare e ignorare un caso particolare o per uscire da un caso corrispondente prima che quel caso abbia completato la sua esecuzione. Per i dettagli, vedi [Break in un'istruzione switch](/guida-al-linguaggio/flusso-di-controllo.md#break-in-unistruzione-switch).
{% endhint %}

Il corpo di ciascun caso *deve* contenere almeno un'istruzione eseguibile. Non è valido scrivere il codice seguente, perché il primo caso è vuoto:

```swift
let anotherCharacter: Character = "a"
switch anotherCharacter {
case "a": // Non valido, il caso ha un corpo vuoto
case "A":
    print("The letter A")
default:
    print("Not the letter A")
}
// Questo segnalerà un errore in fase di compilazione.
```

A differenza di un'istruzione `switch` in C, questa istruzione `switch` non corrisponde sia a `"a"` sia ad `"A"`. Segnala invece un errore in fase di compilazione indicando che `case "a":` non contiene alcuna istruzione eseguibile. Questo approccio evita il passaggio accidentale da un caso all'altro e produce codice più sicuro e più chiaro nelle intenzioni.

Per creare uno `switch` con un singolo caso che corrisponda sia a `"a"` sia ad `"A"`, combina i due valori in un caso composto, separando i valori con delle virgole.

```swift
let anotherCharacter: Character = "a"
switch anotherCharacter {
case "a", "A":
    print("The letter A")
default:
    print("Not the letter A")
}
// Stampa "The letter A".
```

Per la leggibilità, un caso composto può anche essere scritto su più righe. Per maggiori informazioni sui casi composti, vedi [Casi composti](/guida-al-linguaggio/flusso-di-controllo.md#casi-composti).

{% hint style="info" %}
**Nota:** Per proseguire esplicitamente alla fine di un particolare caso `switch`, usa la parola chiave `fallthrough`, come descritto in [Fallthrough](/guida-al-linguaggio/flusso-di-controllo.md#fallthrough).
{% endhint %}

#### Corrispondenza con intervalli <a href="#corrispondenza-con-intervalli" id="corrispondenza-con-intervalli"></a>

I valori nei casi `switch` possono essere verificati per la loro inclusione in un intervallo. Questo esempio usa intervalli numerici per fornire un conteggio in linguaggio naturale per numeri di qualsiasi dimensione:

```swift
let approximateCount = 62
let countedThings = "moons orbiting Saturn"
let naturalCount: String
switch approximateCount {
case 0:
    naturalCount = "no"
case 1..<5:
    naturalCount = "a few"
case 5..<12:
    naturalCount = "several"
case 12..<100:
    naturalCount = "dozens of"
case 100..<1000:
    naturalCount = "hundreds of"
default:
    naturalCount = "many"
}
print("There are \(naturalCount) \(countedThings).")
// Stampa "There are dozens of moons orbiting Saturn."
```

Nell'esempio qui sopra, `approximateCount` viene valutato in un'istruzione `switch`. Ogni `case` confronta quel valore con un numero o un intervallo. Poiché il valore di `approximateCount` è compreso tra 12 e 100, a `naturalCount` viene assegnato il valore `"dozens of"`, e l'esecuzione viene trasferita al di fuori dell'istruzione `switch`.

#### Tuple <a href="#tuple" id="tuple"></a>

Puoi usare le tuple per verificare più valori nella stessa istruzione `switch`. Ciascun elemento della tupla può essere confrontato con un valore o un intervallo di valori diverso. In alternativa, usa il carattere trattino basso (`_`), noto anche come pattern wildcard, per corrispondere a qualsiasi valore possibile.

L'esempio seguente prende un punto (x, y), espresso come semplice tupla di tipo `(Int, Int)`, e lo classifica sul grafico che segue l'esempio.

```swift
let somePoint = (1, 1)
switch somePoint {
case (0, 0):
    print("\(somePoint) is at the origin")
case (_, 0):
    print("\(somePoint) is on the x-axis")
case (0, _):
    print("\(somePoint) is on the y-axis")
case (-2...2, -2...2):
    print("\(somePoint) is inside the box")
default:
    print("\(somePoint) is outside of the box")
}
// Stampa "(1, 1) is inside the box".
```

![](https://3581893755-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FNzatREGwodw9Z93LQYJb%2Fuploads%2FPJrqoyWUof1wusVlXBHr%2FcoordinateGraphSimple%402x.png?alt=media)

L'istruzione `switch` determina se il punto si trova nell'origine (0, 0), sull'asse x rosso, sull'asse y verde, all'interno del riquadro blu 4 per 4 centrato sull'origine, o al di fuori del riquadro.

A differenza del C, Swift consente a più casi `switch` di considerare lo stesso valore o gli stessi valori. Infatti, il punto (0, 0) potrebbe corrispondere a tutti e *quattro* i casi di questo esempio. Tuttavia, se sono possibili più corrispondenze, viene sempre usato il primo caso corrispondente. Il punto (0, 0) corrisponderebbe per primo a `case (0, 0)`, e quindi tutti gli altri casi corrispondenti verrebbero ignorati.

#### Value binding <a href="#value-binding" id="value-binding"></a>

Un caso `switch` può dare un nome al valore o ai valori con cui trova corrispondenza associandoli a costanti o variabili temporanee, da usare nel corpo del caso. Questo comportamento è noto come *value binding* (associazione di valori), perché i valori vengono associati a costanti o variabili temporanee all'interno del corpo del caso.

L'esempio seguente prende un punto (x, y), espresso come tupla di tipo `(Int, Int)`, e lo classifica sul grafico che segue:

```swift
let anotherPoint = (2, 0)
switch anotherPoint {
case (let x, 0):
    print("on the x-axis with an x value of \(x)")
case (0, let y):
    print("on the y-axis with a y value of \(y)")
case let (x, y):
    print("somewhere else at (\(x), \(y))")
}
// Stampa "on the x-axis with an x value of 2".
```

![](https://3581893755-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FNzatREGwodw9Z93LQYJb%2Fuploads%2FAKiwyzDAc4I5TOYV4nr0%2FcoordinateGraphMedium%402x.png?alt=media)

L'istruzione `switch` determina se il punto si trova sull'asse x rosso, sull'asse y verde, o altrove (su nessuno dei due assi).

I tre casi dello `switch` dichiarano le costanti segnaposto `x` e `y`, che assumono temporaneamente uno o entrambi i valori della tupla `anotherPoint`. Il primo caso, `case (let x, 0)`, corrisponde a qualsiasi punto con un valore `y` pari a `0` e assegna il valore `x` del punto alla costante temporanea `x`. Analogamente, il secondo caso, `case (0, let y)`, corrisponde a qualsiasi punto con un valore `x` pari a `0` e assegna il valore `y` del punto alla costante temporanea `y`.

Dopo che le costanti temporanee sono state dichiarate, possono essere usate all'interno del blocco di codice del caso. Qui, vengono usate per stampare la classificazione del punto.

Questa istruzione `switch` non ha un caso `default`. L'ultimo caso, `case let (x, y)`, dichiara una tupla di due costanti segnaposto che può corrispondere a qualsiasi valore. Poiché `anotherPoint` è sempre una tupla di due valori, questo caso corrisponde a tutti i possibili valori rimanenti, e non è necessario un caso `default` per rendere esaustiva l'istruzione `switch`.

#### Where <a href="#where" id="where"></a>

Un caso `switch` può usare una clausola `where` per verificare condizioni aggiuntive.

L'esempio seguente classifica un punto (x, y) sul grafico seguente:

```swift
let yetAnotherPoint = (1, -1)
switch yetAnotherPoint {
case let (x, y) where x == y:
    print("(\(x), \(y)) is on the line x == y")
case let (x, y) where x == -y:
    print("(\(x), \(y)) is on the line x == -y")
case let (x, y):
    print("(\(x), \(y)) is just some arbitrary point")
}
// Stampa "(1, -1) is on the line x == -y".
```

![](https://3581893755-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FNzatREGwodw9Z93LQYJb%2Fuploads%2FRXUadPhIgKqNlc6P7G4o%2FcoordinateGraphComplex%402x.png?alt=media)

L'istruzione `switch` determina se il punto si trova sulla retta diagonale verde in cui `x == y`, sulla retta diagonale viola in cui `x == -y`, o su nessuna delle due.

I tre casi dello `switch` dichiarano le costanti segnaposto `x` e `y`, che assumono temporaneamente i due valori della tupla `yetAnotherPoint`. Queste costanti vengono usate come parte di una clausola `where`, per creare un filtro dinamico. Il caso `switch` corrisponde al valore corrente di `point` solo se la condizione della clausola `where` restituisce `true` per quel valore.

Come nell'esempio precedente, l'ultimo caso corrisponde a tutti i possibili valori rimanenti, e quindi non è necessario un caso `default` per rendere esaustiva l'istruzione `switch`.

#### Casi composti <a href="#casi-composti" id="casi-composti"></a>

Più casi switch che condividono lo stesso corpo possono essere combinati scrivendo diversi pattern dopo `case`, con una virgola tra un pattern e l'altro. Se uno qualsiasi dei pattern corrisponde, allora si considera che il caso corrisponda. I pattern possono essere scritti su più righe se l'elenco è lungo. Per esempio:

```swift
let someCharacter: Character = "e"
switch someCharacter {
case "a", "e", "i", "o", "u":
    print("\(someCharacter) is a vowel")
case "b", "c", "d", "f", "g", "h", "j", "k", "l", "m",
    "n", "p", "q", "r", "s", "t", "v", "w", "x", "y", "z":
    print("\(someCharacter) is a consonant")
default:
    print("\(someCharacter) isn't a vowel or a consonant")
}
// Stampa "e is a vowel".
```

Il primo caso dell'istruzione `switch` corrisponde a tutte e cinque le vocali minuscole della lingua inglese. Analogamente, il suo secondo caso corrisponde a tutte le consonanti minuscole inglesi. Infine, il caso `default` corrisponde a qualsiasi altro carattere.

I casi composti possono includere anche dei value binding. Tutti i pattern di un caso composto devono includere lo stesso insieme di value binding, e ciascun binding deve ricevere un valore dello stesso tipo da tutti i pattern del caso composto. Questo garantisce che, indipendentemente da quale parte del caso composto abbia trovato corrispondenza, il codice nel corpo del caso possa sempre accedere a un valore per i binding e che il valore abbia sempre lo stesso tipo.

```swift
let stillAnotherPoint = (9, 0)
switch stillAnotherPoint {
case (let distance, 0), (0, let distance):
    print("On an axis, \(distance) from the origin")
default:
    print("Not on an axis")
}
// Stampa "On an axis, 9 from the origin".
```

Il `case` qui sopra ha due pattern: `(let distance, 0)` corrisponde ai punti sull'asse x e `(0, let distance)` corrisponde ai punti sull'asse y. Entrambi i pattern includono un binding per `distance` e `distance` è un intero in entrambi i pattern — il che significa che il codice nel corpo del `case` può sempre accedere a un valore per `distance`.

## Pattern <a href="#pattern" id="pattern"></a>

Negli esempi precedenti, ogni caso switch include un pattern che indica quali valori corrispondono a quel caso. Puoi anche usare un pattern come condizione di un'istruzione `if`. Ecco come appare:

```swift
let somePoint = (12, 100)
if case (let x, 100) = somePoint {
    print("Found a point on the y=100 line, at \(x)")
}
// Stampa "Found a point on the y=100 line, at 12".
```

In questo codice, la condizione dell'istruzione `if` inizia con `case`, a indicare che la condizione è un pattern anziché un valore booleano. Se il pattern corrisponde, allora la condizione dell'`if` è considerata vera, e quindi viene eseguito il codice nel corpo dell'istruzione `if`. I pattern che puoi scrivere dopo `if case` sono gli stessi che puoi scrivere in un caso switch.

In un ciclo `for`-`in`, puoi dare dei nomi a parti del valore usando un pattern di value binding, anche senza scrivere `case` nel tuo codice:

```swift
let points = [(10, 0), (30, -30), (-20, 0)]

for (x, y) in points {
    if y == 0 {
        print("Found a point on the x-axis at \(x)")
    }
}
// Stampa "Found a point on the x-axis at 10".
// Stampa "Found a point on the x-axis at -20".
```

Il ciclo `for`-`in` qui sopra itera su un array di tuple, associando il primo e il secondo elemento delle tuple alle costanti `x` e `y`. Le istruzioni all'interno del ciclo possono usare quelle costanti, come l'istruzione `if` che verifica se il punto si trova sull'asse x. Un modo più conciso di scrivere questo codice consiste nel combinare i value binding e la condizione usando un ciclo `for`-`case`-`in`. Il codice seguente ha lo stesso comportamento del ciclo `for`-`in` qui sopra:

```swift
for case (let x, 0) in points {
    print("Found a point on the x-axis at \(x)")
}
// Stampa "Found a point on the x-axis at 10".
// Stampa "Found a point on the x-axis at -20".
```

In questo codice, la condizione è integrata nel ciclo `for`-`case`-`in` come parte del pattern. Le istruzioni del ciclo `for`-`case`-`in` vengono eseguite solo per i punti sull'asse x. Questo codice produce lo stesso risultato del ciclo `for`-`in` qui sopra, ma è un modo più compatto di iterare solo su certi elementi di una collezione.

Un ciclo `for`-`case`-`in` può includere anche una clausola `where`, per verificare una condizione aggiuntiva. Le istruzioni all'interno del ciclo vengono eseguite solo quando la clausola `where` corrisponde all'elemento corrente. Per esempio:

```swift
for case let (x, y) in points where x == y || x == -y  {
    print("Found (\(x), \(y)) along a line through the origin")
}
// Stampa "Found (30, -30) along a line through the origin".
```

Questo codice associa il primo e il secondo elemento della tupla a `x` e `y` come costanti, e poi ne verifica i valori nella clausola `where`. Se la clausola `where` è `true`, allora viene eseguito il codice nel corpo del ciclo `for`; altrimenti, l'iterazione prosegue con l'elemento successivo.

Poiché i pattern possono associare valori, le istruzioni `if`-`case` e i cicli `for`-`case`-`in` sono utili per lavorare con le enumerazioni che hanno valori associati, come descritto in [Valori associati](/guida-al-linguaggio/enumerazioni.md#valori-associati).

## Istruzioni di trasferimento del controllo <a href="#istruzioni-di-trasferimento-del-controllo" id="istruzioni-di-trasferimento-del-controllo"></a>

Le *istruzioni di trasferimento del controllo* cambiano l'ordine in cui il tuo codice viene eseguito, trasferendo il controllo da una porzione di codice a un'altra. Swift ha cinque istruzioni di trasferimento del controllo:

* `continue`
* `break`
* `fallthrough`
* `return`
* `throw`

Le istruzioni `continue`, `break` e `fallthrough` sono descritte di seguito. L'istruzione `return` è descritta in [Funzioni](/guida-al-linguaggio/funzioni.md), e l'istruzione `throw` è descritta in [Propagare gli errori usando funzioni che lanciano errori](/guida-al-linguaggio/gestione-degli-errori.md#propagare-gli-errori-usando-funzioni-che-lanciano-errori).

### Continue <a href="#continue" id="continue"></a>

L'istruzione `continue` dice a un ciclo di interrompere ciò che sta facendo e di ricominciare dall'inizio dell'iterazione successiva del ciclo. Dice “ho finito con l'iterazione corrente del ciclo” senza uscire del tutto dal ciclo.

L'esempio seguente rimuove tutte le vocali e gli spazi da una stringa minuscola per creare una frase enigmatica da indovinare:

```swift
let puzzleInput = "great minds think alike"
var puzzleOutput = ""
let charactersToRemove: [Character] = ["a", "e", "i", "o", "u", " "]
for character in puzzleInput {
    if charactersToRemove.contains(character) {
        continue
    }
    puzzleOutput.append(character)
}
print(puzzleOutput)
// Stampa "grtmndsthnklk".
```

Il codice qui sopra chiama la parola chiave `continue` ogni volta che trova una vocale o uno spazio, facendo sì che l'iterazione corrente del ciclo termini immediatamente e che si salti direttamente all'inizio dell'iterazione successiva.

### Break <a href="#break" id="break"></a>

L'istruzione `break` termina immediatamente l'esecuzione di un'intera istruzione di controllo del flusso. L'istruzione `break` può essere usata all'interno di un'istruzione `switch` o di un ciclo quando vuoi terminare l'esecuzione dello `switch` o del ciclo prima di quanto accadrebbe altrimenti.

#### Break in un ciclo <a href="#break-in-un-ciclo" id="break-in-un-ciclo"></a>

Quando viene usato all'interno di un ciclo, `break` termina immediatamente l'esecuzione del ciclo e trasferisce il controllo al codice che segue la parentesi graffa di chiusura del ciclo (`}`). Non viene eseguito altro codice dell'iterazione corrente del ciclo, e non vengono avviate ulteriori iterazioni del ciclo.

#### Break in un'istruzione switch <a href="#break-in-unistruzione-switch" id="break-in-unistruzione-switch"></a>

Quando viene usato all'interno di un'istruzione `switch`, `break` fa sì che l'istruzione `switch` termini immediatamente la sua esecuzione e trasferisca il controllo al codice che segue la parentesi graffa di chiusura dell'istruzione `switch` (`}`).

Questo comportamento può essere usato per trovare e ignorare uno o più casi in un'istruzione `switch`. Poiché l'istruzione `switch` di Swift è esaustiva e non consente casi vuoti, a volte è necessario trovare e ignorare deliberatamente un caso per rendere esplicite le tue intenzioni. Lo fai scrivendo l'istruzione `break` come intero corpo del caso che vuoi ignorare. Quando quel caso trova corrispondenza nell'istruzione `switch`, l'istruzione `break` all'interno del caso termina immediatamente l'esecuzione dell'istruzione `switch`.

{% hint style="info" %}
**Nota:** Un caso `switch` che contiene solo un commento viene segnalato come errore in fase di compilazione. I commenti non sono istruzioni e non fanno sì che un caso `switch` venga ignorato. Usa sempre un'istruzione `break` per ignorare un caso `switch`.
{% endhint %}

L'esempio seguente esegue uno switch su un valore `Character` e determina se rappresenta il simbolo di un numero in una di quattro lingue. Per brevità, più valori sono coperti in un unico caso `switch`.

```swift
let numberSymbol: Character = "三"  // simbolo cinese per il numero 3
var possibleIntegerValue: Int?
switch numberSymbol {
case "1", "١", "一", "๑":
    possibleIntegerValue = 1
case "2", "٢", "二", "๒":
    possibleIntegerValue = 2
case "3", "٣", "三", "๓":
    possibleIntegerValue = 3
case "4", "٤", "四", "๔":
    possibleIntegerValue = 4
default:
    break
}
if let integerValue = possibleIntegerValue {
    print("The integer value of \(numberSymbol) is \(integerValue).")
} else {
    print("An integer value couldn't be found for \(numberSymbol).")
}
// Stampa "The integer value of 三 is 3."
```

Questo esempio verifica `numberSymbol` per determinare se è un simbolo latino, arabo, cinese o thailandese per i numeri da `1` a `4`. Se viene trovata una corrispondenza, uno dei casi dell'istruzione `switch` imposta una variabile opzionale `Int?` chiamata `possibleIntegerValue` a un valore intero appropriato.

Dopo che l'istruzione `switch` ha completato la sua esecuzione, l'esempio usa l'optional binding per determinare se è stato trovato un valore. La variabile `possibleIntegerValue` ha un valore iniziale implicito `nil` in virtù del fatto di essere di tipo opzionale, e quindi l'optional binding avrà successo solo se `possibleIntegerValue` è stata impostata a un valore effettivo da uno dei primi quattro casi dell'istruzione `switch`.

Poiché non è pratico elencare ogni possibile valore `Character` nell'esempio qui sopra, un caso `default` gestisce tutti i caratteri che non trovano corrispondenza. Questo caso `default` non ha bisogno di eseguire alcuna azione, e quindi è scritto con un'unica istruzione `break` come corpo. Non appena il caso `default` trova corrispondenza, l'istruzione `break` termina l'esecuzione dell'istruzione `switch`, e l'esecuzione del codice prosegue dall'istruzione `if let`.

### Fallthrough <a href="#fallthrough" id="fallthrough"></a>

In Swift, le istruzioni `switch` non proseguono dal fondo di ciascun caso al caso successivo. Cioè, l'intera istruzione `switch` completa la sua esecuzione non appena il primo caso corrispondente è completato. Al contrario, il C richiede di inserire un'istruzione `break` esplicita alla fine di ogni caso `switch` per impedire il fallthrough. Evitare il fallthrough predefinito significa che le istruzioni `switch` di Swift sono molto più concise e prevedibili delle loro controparti in C, e quindi evitano di eseguire per errore più casi `switch`.

Se hai bisogno del comportamento di fallthrough in stile C, puoi abilitare questo comportamento caso per caso con la parola chiave `fallthrough`. L'esempio seguente usa `fallthrough` per creare una descrizione testuale di un numero.

```swift
let integerToDescribe = 5
var description = "The number \(integerToDescribe) is"
switch integerToDescribe {
case 2, 3, 5, 7, 11, 13, 17, 19:
    description += " a prime number, and also"
    fallthrough
default:
    description += " an integer."
}
print(description)
// Stampa "The number 5 is a prime number, and also an integer."
```

Questo esempio dichiara una nuova variabile `String` chiamata `description` e le assegna un valore iniziale. La funzione considera poi il valore di `integerToDescribe` usando un'istruzione `switch`. Se il valore di `integerToDescribe` è uno dei numeri primi dell'elenco, la funzione aggiunge del testo alla fine di `description`, per indicare che il numero è primo. Poi usa la parola chiave `fallthrough` per “cadere” anche nel caso `default`. Il caso `default` aggiunge un po' di testo extra alla fine della descrizione, e l'istruzione `switch` è completata.

A meno che il valore di `integerToDescribe` non si trovi nell'elenco dei numeri primi noti, non trova affatto corrispondenza nel primo caso `switch`. Poiché non ci sono altri casi specifici, `integerToDescribe` trova corrispondenza nel caso `default`.

Dopo che l'istruzione `switch` ha terminato l'esecuzione, la descrizione del numero viene stampata usando la funzione `print(_:separator:terminator:)`. In questo esempio, il numero `5` viene correttamente identificato come numero primo.

{% hint style="info" %}
**Nota:** La parola chiave `fallthrough` non verifica le condizioni del caso del caso `switch` in cui fa cadere l'esecuzione. La parola chiave `fallthrough` fa semplicemente passare l'esecuzione del codice direttamente alle istruzioni all'interno del blocco del caso successivo (o del caso `default`), come nel comportamento standard dell'istruzione `switch` del C.
{% endhint %}

### Istruzioni etichettate <a href="#istruzioni-etichettate" id="istruzioni-etichettate"></a>

In Swift, puoi annidare cicli e istruzioni condizionali all'interno di altri cicli e istruzioni condizionali per creare strutture di controllo del flusso complesse. Tuttavia, sia i cicli sia le istruzioni condizionali possono usare l'istruzione `break` per terminare prematuramente la loro esecuzione. Pertanto, a volte è utile essere espliciti su quale ciclo o istruzione condizionale vuoi che un'istruzione `break` termini. Analogamente, se hai più cicli annidati, può essere utile essere espliciti su quale ciclo debba influire l'istruzione `continue`.

Per raggiungere questi obiettivi, puoi contrassegnare un ciclo o un'istruzione condizionale con un'*etichetta di istruzione*. Con un'istruzione condizionale, puoi usare un'etichetta di istruzione con l'istruzione `break` per terminare l'esecuzione dell'istruzione etichettata. Con un ciclo, puoi usare un'etichetta di istruzione con l'istruzione `break` o `continue` per terminare o continuare l'esecuzione dell'istruzione etichettata.

Un'istruzione etichettata si indica collocando un'etichetta sulla stessa riga della parola chiave introduttiva dell'istruzione, seguita da due punti. Ecco un esempio di questa sintassi per un ciclo `while`, anche se il principio è lo stesso per tutti i cicli e le istruzioni `switch`:

```swift
<#label name#>: while <#condition#> {
   <#statements#>
}
```

L'esempio seguente usa le istruzioni `break` e `continue` con un ciclo `while` etichettato per una versione adattata del gioco *Serpenti e scale* che hai visto in precedenza in questo capitolo. Questa volta, il gioco ha una regola in più:

* Per vincere, devi arrivare *esattamente* sulla casella 25.

Se un determinato lancio di dado ti porterebbe oltre la casella 25, devi lanciare di nuovo finché non ottieni il numero esatto necessario per arrivare sulla casella 25.

Il tabellone di gioco è lo stesso di prima.

![](https://3581893755-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FNzatREGwodw9Z93LQYJb%2Fuploads%2F4TKFWiSgohkE4yTOxUAU%2FsnakesAndLadders%402x.png?alt=media)

I valori di `finalSquare`, `board`, `square` e `diceRoll` vengono inizializzati nello stesso modo di prima:

```swift
let finalSquare = 25
var board = [Int](repeating: 0, count: finalSquare + 1)
board[03] = +08; board[06] = +11; board[09] = +09; board[10] = +02
board[14] = -10; board[19] = -11; board[22] = -02; board[24] = -08
var square = 0
var diceRoll = 0
```

Questa versione del gioco usa un ciclo `while` e un'istruzione `switch` per implementare la logica del gioco. Il ciclo `while` ha un'etichetta di istruzione chiamata `gameLoop` per indicare che è il ciclo di gioco principale del gioco Serpenti e scale.

La condizione del ciclo `while` è `while square != finalSquare`, per riflettere il fatto che devi arrivare esattamente sulla casella 25.

```swift
gameLoop: while square != finalSquare {
    diceRoll += 1
    if diceRoll == 7 { diceRoll = 1 }
    switch square + diceRoll {
    case finalSquare:
        // diceRoll ci porterà sulla casella finale, quindi la partita è finita
        break gameLoop
    case let newSquare where newSquare > finalSquare:
        // diceRoll ci porterà oltre la casella finale, quindi lancia di nuovo
        continue gameLoop
    default:
        // questa è una mossa valida, quindi determinane l'effetto
        square += diceRoll
        square += board[square]
    }
}
print("Game over!")
```

Il dado viene lanciato all'inizio di ogni ciclo. Invece di spostare immediatamente il giocatore, il ciclo usa un'istruzione `switch` per considerare il risultato della mossa e per determinare se la mossa è consentita:

* Se il lancio del dado porterà il giocatore sulla casella finale, la partita è finita. L'istruzione `break gameLoop` trasferisce il controllo alla prima riga di codice al di fuori del ciclo `while`, il che termina la partita.
* Se il lancio del dado porterà il giocatore *oltre* la casella finale, la mossa non è valida e il giocatore deve lanciare di nuovo. L'istruzione `continue gameLoop` termina l'iterazione corrente del ciclo `while` e inizia l'iterazione successiva del ciclo.
* In tutti gli altri casi, il lancio del dado è una mossa valida. Il giocatore avanza di `diceRoll` caselle, e la logica del gioco verifica la presenza di serpenti e scale. Il ciclo quindi termina, e il controllo torna alla condizione del `while` per decidere se è necessario un altro turno.

{% hint style="info" %}
**Nota:** Se l'istruzione `break` qui sopra non usasse l'etichetta `gameLoop`, uscirebbe dall'istruzione `switch`, non dall'istruzione `while`. Usare l'etichetta `gameLoop` rende chiaro quale istruzione di controllo debba essere terminata.

Non è strettamente necessario usare l'etichetta `gameLoop` quando si chiama `continue gameLoop` per passare all'iterazione successiva del ciclo. Nel gioco c'è un solo ciclo, e quindi non c'è ambiguità su quale ciclo influirà l'istruzione `continue`. Tuttavia, non c'è alcun male nell'usare l'etichetta `gameLoop` con l'istruzione `continue`. Farlo è coerente con l'uso dell'etichetta insieme all'istruzione `break` e aiuta a rendere la logica del gioco più chiara da leggere e da comprendere.
{% endhint %}

## Uscita anticipata <a href="#uscita-anticipata" id="uscita-anticipata"></a>

Un'istruzione `guard`, come un'istruzione `if`, esegue delle istruzioni a seconda del valore booleano di un'espressione. Usi un'istruzione `guard` per richiedere che una condizione sia vera affinché il codice che segue l'istruzione `guard` venga eseguito. A differenza di un'istruzione `if`, un'istruzione `guard` ha sempre una clausola `else` — il codice all'interno della clausola `else` viene eseguito se la condizione non è vera.

```swift
func greet(person: [String: String]) {
    guard let name = person["name"] else {
        return
    }

    print("Hello \(name)!")

    guard let location = person["location"] else {
        print("I hope the weather is nice near you.")
        return
    }

    print("I hope the weather is nice in \(location).")
}

greet(person: ["name": "John"])
// Stampa "Hello John!"
// Stampa "I hope the weather is nice near you."
greet(person: ["name": "Jane", "location": "Cupertino"])
// Stampa "Hello Jane!"
// Stampa "I hope the weather is nice in Cupertino."
```

Se la condizione dell'istruzione `guard` è soddisfatta, l'esecuzione del codice prosegue dopo la parentesi graffa di chiusura dell'istruzione `guard`. Tutte le variabili o costanti a cui sono stati assegnati valori usando un optional binding come parte della condizione sono disponibili per il resto del blocco di codice in cui compare l'istruzione `guard`.

Se quella condizione non è soddisfatta, viene eseguito il codice all'interno del ramo `else`. Quel ramo deve trasferire il controllo per uscire dal blocco di codice in cui compare l'istruzione `guard`. Può farlo con un'istruzione di trasferimento del controllo come `return`, `break`, `continue` o `throw`, oppure può chiamare una funzione o un metodo che non restituisce mai, come `fatalError(_:file:line:)`.

Usare un'istruzione `guard` per i requisiti migliora la leggibilità del tuo codice, rispetto a eseguire la stessa verifica con un'istruzione `if`. Ti permette di scrivere il codice che viene tipicamente eseguito senza racchiuderlo in un blocco `else`, e ti permette di mantenere il codice che gestisce un requisito violato accanto al requisito stesso.

## Azioni rinviate <a href="#azioni-rinviate" id="azioni-rinviate"></a>

A differenza dei costrutti di controllo del flusso come `if` e `while`, che ti permettono di controllare se una parte del tuo codice viene eseguita o quante volte viene eseguita, `defer` controlla *quando* viene eseguita una porzione di codice. Usi un blocco `defer` per scrivere codice che verrà eseguito in seguito, quando il tuo programma raggiunge la fine dell'ambito corrente. Per esempio:

```swift
var score = 1
if score < 10 {
    defer {
        print(score)
    }
    score += 5
}
// Stampa "6".
```

Nell'esempio qui sopra, il codice all'interno del blocco `defer` viene eseguito prima di uscire dal corpo dell'istruzione `if`. Prima viene eseguito il codice dell'istruzione `if`, che incrementa `score` di cinque. Poi, prima di uscire dall'ambito dell'istruzione `if`, viene eseguito il codice rinviato, che stampa `score`.

Il codice all'interno del `defer` viene sempre eseguito, indipendentemente da come il programma esce da quell'ambito. Ciò comprende codice come un'uscita anticipata da una funzione, l'uscita da un ciclo `for`, o il lancio di un errore. Questo comportamento rende `defer` utile per le operazioni in cui devi garantire che avvenga una coppia di azioni — come allocare e liberare manualmente la memoria, aprire e chiudere descrittori di file a basso livello, e iniziare e terminare transazioni in un database — perché puoi scrivere entrambe le azioni una accanto all'altra nel tuo codice. Per esempio, il codice seguente dà un bonus temporaneo al punteggio, aggiungendo e sottraendo 100 all'interno di una porzione di codice:

```swift
var score = 3
if score < 100 {
    score += 100
    defer {
        score -= 100
    }
    // Qui va altro codice che usa il punteggio con il suo bonus.
    print(score)
}
// Stampa "103".
```

Se scrivi più di un blocco `defer` nello stesso ambito, il primo che specifichi è l'ultimo a essere eseguito.

```swift
if score < 10 {
    defer {
        print(score)
    }
    defer {
        print("The score is:")
    }
    score += 5
}
// Stampa "The score is:".
// Stampa "6".
```

Se il tuo programma smette di funzionare — per esempio, a causa di un errore in fase di esecuzione o di un crash — il codice rinviato non viene eseguito. Tuttavia, il codice rinviato viene eseguito dopo che è stato lanciato un errore; per informazioni sull'uso di `defer` con la gestione degli errori, vedi [Specificare azioni di pulizia](/guida-al-linguaggio/gestione-degli-errori.md#specificare-azioni-di-pulizia).

## Verificare la disponibilità delle API <a href="#verificare-la-disponibilita-delle-api" id="verificare-la-disponibilita-delle-api"></a>

Swift ha un supporto integrato per verificare la disponibilità delle API, che garantisce che tu non usi per errore API non disponibili su un dato deployment target.

Il compilatore usa le informazioni sulla disponibilità presenti nell'SDK per verificare che tutte le API usate nel tuo codice siano disponibili sul deployment target specificato dal tuo progetto. Swift segnala un errore in fase di compilazione se provi a usare un'API non disponibile.

Usi una *condizione di disponibilità* in un'istruzione `if` o `guard` per eseguire in modo condizionale un blocco di codice, a seconda che le API che vuoi usare siano disponibili in fase di esecuzione. Il compilatore usa le informazioni della condizione di disponibilità quando verifica che le API di quel blocco di codice siano disponibili.

```swift
if #available(iOS 10, macOS 10.12, *) {
    // Usa le API di iOS 10 su iOS, e le API di macOS 10.12 su macOS
} else {
    // Ripiega sulle API precedenti di iOS e macOS
}
```

La condizione di disponibilità qui sopra specifica che su iOS il corpo dell'istruzione `if` viene eseguito solo su iOS 10 e versioni successive; su macOS, solo su macOS 10.12 e versioni successive. L'ultimo argomento, `*`, è obbligatorio e specifica che su qualsiasi altra piattaforma il corpo dell'`if` viene eseguito sul deployment target minimo specificato dal tuo target.

Nella sua forma generale, la condizione di disponibilità accetta un elenco di nomi di piattaforme e versioni. Usi nomi di piattaforme come `iOS`, `macOS`, `watchOS`, `tvOS` e `visionOS` — per l'elenco completo, vedi [Attributi di dichiarazione](/riferimento-del-linguaggio/attributi.md#attributi-di-dichiarazione). Oltre a specificare numeri di versione principali come iOS 8 o macOS 10.10, puoi specificare numeri di versione secondari come iOS 11.2.6 e macOS 10.13.3.

```swift
if #available(<#platform name#> <#version#>, <#...#>, *) {
    <#statements to execute if the APIs are available#>
} else {
    <#fallback statements to execute if the APIs are unavailable#>
}
```

Quando usi una condizione di disponibilità con un'istruzione `guard`, questa affina le informazioni sulla disponibilità usate per il resto del codice in quel blocco di codice.

```swift
@available(macOS 10.12, *)
struct ColorPreference {
    var bestColor = "blue"
}

func chooseBestColor() -> String {
    guard #available(macOS 10.12, *) else {
       return "gray"
    }
    let colors = ColorPreference()
    return colors.bestColor
}
```

Nell'esempio qui sopra, la struttura `ColorPreference` richiede macOS 10.12 o versioni successive. La funzione `chooseBestColor()` inizia con un guard di disponibilità. Se la versione della piattaforma è troppo vecchia per usare `ColorPreference`, ripiega su un comportamento sempre disponibile. Dopo l'istruzione `guard`, puoi usare le API che richiedono macOS 10.12 o versioni successive.

Oltre a `#available`, Swift supporta anche la verifica opposta usando una condizione di non disponibilità. Per esempio, le due verifiche seguenti fanno la stessa cosa:

```swift
if #available(iOS 10, *) {
} else {
    // Codice di ripiego
}

if #unavailable(iOS 10) {
    // Codice di ripiego
}
```

Usare la forma `#unavailable` aiuta a rendere il tuo codice più leggibile quando la verifica contiene solo codice di ripiego.
