> 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/conteggio-automatico-dei-riferimenti.md).

# Conteggio automatico dei riferimenti (Automatic Reference Counting)

Modella il ciclo di vita degli oggetti e le loro relazioni.

Swift usa il *conteggio automatico dei riferimenti* (ARC, Automatic Reference Counting) per tenere traccia dell'uso della memoria della tua app e gestirlo. Nella maggior parte dei casi, ciò significa che in Swift la gestione della memoria “funziona e basta”, e non hai bisogno di occuparti personalmente della gestione della memoria. ARC libera automaticamente la memoria usata dalle istanze di classe quando quelle istanze non sono più necessarie.

Tuttavia, in alcuni casi ARC ha bisogno di più informazioni sulle relazioni tra le parti del tuo codice per poter gestire la memoria per te. Questo capitolo descrive quelle situazioni e mostra come permettere ad ARC di gestire tutta la memoria della tua app. L'uso di ARC in Swift è molto simile all'approccio descritto in [Transitioning to ARC Release Notes](https://developer.apple.com/library/content/releasenotes/ObjectiveC/RN-TransitioningToARC/Introduction/Introduction.html) per l'uso di ARC con Objective-C.

Il conteggio dei riferimenti si applica solo alle istanze delle classi. Strutture ed enumerazioni sono tipi valore, non tipi riferimento, e non vengono memorizzate e passate per riferimento.

## Come funziona ARC <a href="#come-funziona-arc" id="come-funziona-arc"></a>

Ogni volta che crei una nuova istanza di una classe, ARC alloca un blocco di memoria per memorizzare le informazioni su quell'istanza. Questa memoria contiene informazioni sul tipo dell'istanza, insieme ai valori di tutte le proprietà memorizzate associate a quell'istanza.

Inoltre, quando un'istanza non è più necessaria, ARC libera la memoria usata da quell'istanza in modo che la memoria possa essere invece usata per altri scopi. Questo garantisce che le istanze di classe non occupino spazio in memoria quando non sono più necessarie.

Tuttavia, se ARC deallocasse un'istanza ancora in uso, non sarebbe più possibile accedere alle proprietà di quell'istanza, né chiamarne i metodi. Anzi, se provassi ad accedere all'istanza, molto probabilmente la tua app andrebbe in crash.

Per assicurarsi che le istanze non scompaiano mentre sono ancora necessarie, ARC tiene traccia di quante proprietà, costanti e variabili fanno attualmente riferimento a ciascuna istanza di classe. ARC non deallocherà un'istanza finché esiste ancora almeno un riferimento attivo a quell'istanza.

Per rendere possibile tutto ciò, ogni volta che assegni un'istanza di classe a una proprietà, costante o variabile, quella proprietà, costante o variabile crea un *riferimento forte* all'istanza. Il riferimento è chiamato "forte" perché mantiene una presa salda su quell'istanza, e non permette che venga deallocata finché quel riferimento forte rimane.

## ARC in azione <a href="#arc-in-azione" id="arc-in-azione"></a>

Ecco un esempio di come funziona il conteggio automatico dei riferimenti. Questo esempio inizia con una semplice classe chiamata `Person`, che definisce una proprietà costante memorizzata chiamata `name`:

```swift
class Person {
    let name: String
    init(name: String) {
        self.name = name
        print("\(name) is being initialized")
    }
    deinit {
        print("\(name) is being deinitialized")
    }
}
```

La classe `Person` ha un inizializzatore che imposta la proprietà `name` dell'istanza e stampa un messaggio per indicare che l'inizializzazione è in corso. La classe `Person` ha anche un deinizializzatore che stampa un messaggio quando un'istanza della classe viene deallocata.

Il frammento di codice successivo definisce tre variabili di tipo `Person?`, che vengono usate per impostare più riferimenti a una nuova istanza di `Person` nei frammenti di codice successivi. Poiché queste variabili sono di un tipo opzionale (`Person?`, non `Person`), vengono inizializzate automaticamente con un valore `nil`, e al momento non fanno riferimento ad alcuna istanza di `Person`.

```swift
var reference1: Person?
var reference2: Person?
var reference3: Person?
```

Ora puoi creare una nuova istanza di `Person` e assegnarla a una di queste tre variabili:

```swift
reference1 = Person(name: "John Appleseed")
// Stampa "John Appleseed is being initialized".
```

Nota che il messaggio `"John Appleseed is being initialized"` viene stampato nel momento in cui chiami l'inizializzatore della classe `Person`. Questo conferma che l'inizializzazione è avvenuta.

Poiché la nuova istanza di `Person` è stata assegnata alla variabile `reference1`, ora c'è un riferimento forte da `reference1` alla nuova istanza di `Person`. Poiché c'è almeno un riferimento forte, ARC si assicura che questa `Person` venga mantenuta in memoria e non venga deallocata.

Se assegni la stessa istanza di `Person` ad altre due variabili, vengono stabiliti altri due riferimenti forti a quell'istanza:

```swift
reference2 = reference1
reference3 = reference1
```

Ora ci sono *tre* riferimenti forti a questa singola istanza di `Person`.

Se interrompi due di questi riferimenti forti (compreso il riferimento originale) assegnando `nil` a due delle variabili, rimane un solo riferimento forte, e l'istanza di `Person` non viene deallocata:

```swift
reference1 = nil
reference2 = nil
```

ARC non dealloca l'istanza di `Person` finché non viene interrotto il terzo e ultimo riferimento forte, momento in cui è chiaro che non stai più usando l'istanza di `Person`:

```swift
reference3 = nil
// Stampa "John Appleseed is being deinitialized".
```

## Cicli di riferimenti forti tra istanze di classe <a href="#cicli-di-riferimenti-forti-tra-istanze-di-classe" id="cicli-di-riferimenti-forti-tra-istanze-di-classe"></a>

Negli esempi qui sopra, ARC è in grado di tenere traccia del numero di riferimenti alla nuova istanza di `Person` che crei e di deallocare quell'istanza di `Person` quando non è più necessaria.

Tuttavia, è possibile scrivere codice in cui un'istanza di una classe non arriva *mai* a un punto in cui ha zero riferimenti forti. Questo può accadere se due istanze di classe mantengono un riferimento forte l'una all'altra, in modo tale che ciascuna istanza tenga in vita l'altra. Questo è noto come *ciclo di riferimenti forti*.

Risolvi i cicli di riferimenti forti definendo alcune delle relazioni tra le classi come riferimenti deboli (weak) o non posseduti (unowned) anziché come riferimenti forti. Questo processo è descritto in [Risolvere i cicli di riferimenti forti tra istanze di classe](/guida-al-linguaggio/conteggio-automatico-dei-riferimenti.md#risolvere-i-cicli-di-riferimenti-forti-tra-istanze-di-classe). Tuttavia, prima di imparare a risolvere un ciclo di riferimenti forti, è utile capire come si origina un ciclo del genere.

Ecco un esempio di come un ciclo di riferimenti forti possa essere creato per errore. Questo esempio definisce due classi chiamate `Person` e `Apartment`, che modellano un condominio e i suoi residenti:

```swift
class Person {
    let name: String
    init(name: String) { self.name = name }
    var apartment: Apartment?
    deinit { print("\(name) is being deinitialized") }
}

class Apartment {
    let unit: String
    init(unit: String) { self.unit = unit }
    var tenant: Person?
    deinit { print("Apartment \(unit) is being deinitialized") }
}
```

Ogni istanza di `Person` ha una proprietà `name` di tipo `String` e una proprietà opzionale `apartment` inizialmente `nil`. La proprietà `apartment` è opzionale, perché una persona potrebbe non avere sempre un appartamento.

Analogamente, ogni istanza di `Apartment` ha una proprietà `unit` di tipo `String` e ha una proprietà opzionale `tenant` inizialmente `nil`. La proprietà tenant è opzionale perché un appartamento potrebbe non avere sempre un inquilino.

Entrambe queste classi definiscono anche un deinizializzatore, che stampa il fatto che un'istanza di quella classe viene deinizializzata. Questo ti permette di vedere se le istanze di `Person` e di `Apartment` vengono deallocate come previsto.

Il frammento di codice successivo definisce due variabili di tipo opzionale chiamate `john` e `unit4A`, che verranno impostate più avanti a una specifica istanza di `Apartment` e di `Person`. Entrambe queste variabili hanno un valore iniziale di `nil`, in virtù del fatto di essere opzionali:

```swift
var john: Person?
var unit4A: Apartment?
```

Ora puoi creare una specifica istanza di `Person` e un'istanza di `Apartment` e assegnare queste nuove istanze alle variabili `john` e `unit4A`:

```swift
john = Person(name: "John Appleseed")
unit4A = Apartment(unit: "4A")
```

Ecco come appaiono i riferimenti forti dopo aver creato e assegnato queste due istanze. La variabile `john` ora ha un riferimento forte alla nuova istanza di `Person`, e la variabile `unit4A` ha un riferimento forte alla nuova istanza di `Apartment`:

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

Ora puoi collegare le due istanze in modo che la persona abbia un appartamento, e l'appartamento abbia un inquilino. Nota che si usa un punto esclamativo (`!`) per fare l'unwrapping e accedere alle istanze memorizzate all'interno delle variabili opzionali `john` e `unit4A`, in modo da poter impostare le proprietà di quelle istanze:

```swift
john!.apartment = unit4A
unit4A!.tenant = john
```

Ecco come appaiono i riferimenti forti dopo che hai collegato le due istanze:

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

Purtroppo, collegare queste due istanze crea un ciclo di riferimenti forti tra di esse. L'istanza di `Person` ora ha un riferimento forte all'istanza di `Apartment`, e l'istanza di `Apartment` ha un riferimento forte all'istanza di `Person`. Pertanto, quando interrompi i riferimenti forti mantenuti dalle variabili `john` e `unit4A`, i conteggi dei riferimenti non scendono a zero, e le istanze non vengono deallocate da ARC:

```swift
john = nil
unit4A = nil
```

Nota che nessuno dei due deinizializzatori è stato chiamato quando hai impostato queste due variabili a `nil`. Il ciclo di riferimenti forti impedisce che le istanze di `Person` e di `Apartment` vengano mai deallocate, causando una perdita di memoria (memory leak) nella tua app.

Ecco come appaiono i riferimenti forti dopo che hai impostato le variabili `john` e `unit4A` a `nil`:

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

I riferimenti forti tra l'istanza di `Person` e l'istanza di `Apartment` rimangono e non possono essere interrotti.

## Risolvere i cicli di riferimenti forti tra istanze di classe <a href="#risolvere-i-cicli-di-riferimenti-forti-tra-istanze-di-classe" id="risolvere-i-cicli-di-riferimenti-forti-tra-istanze-di-classe"></a>

Swift fornisce due modi per risolvere i cicli di riferimenti forti quando lavori con proprietà di tipo classe: i riferimenti deboli (weak) e i riferimenti non posseduti (unowned).

I riferimenti weak e unowned permettono a un'istanza in un ciclo di riferimenti di fare riferimento all'altra istanza *senza* mantenere una presa forte su di essa. Le istanze possono quindi fare riferimento l'una all'altra senza creare un ciclo di riferimenti forti.

Usa un riferimento weak quando l'altra istanza ha una durata di vita più breve — cioè, quando l'altra istanza può essere deallocata per prima. Nell'esempio `Apartment` qui sopra, è appropriato che un appartamento possa non avere alcun inquilino in un certo momento della sua vita, e quindi in questo caso un riferimento weak è un modo appropriato per interrompere il ciclo di riferimenti. Al contrario, usa un riferimento unowned quando l'altra istanza ha la stessa durata di vita o una durata di vita più lunga.

### Riferimenti weak <a href="#riferimenti-weak" id="riferimenti-weak"></a>

Un *riferimento weak* (debole) è un riferimento che non mantiene una presa forte sull'istanza a cui fa riferimento, e quindi non impedisce ad ARC di eliminare l'istanza referenziata. Questo comportamento impedisce al riferimento di diventare parte di un ciclo di riferimenti forti. Indichi un riferimento weak collocando la parola chiave `weak` prima della dichiarazione di una proprietà o di una variabile.

Poiché un riferimento weak non mantiene una presa forte sull'istanza a cui fa riferimento, è possibile che quell'istanza venga deallocata mentre il riferimento weak vi fa ancora riferimento. Pertanto, ARC imposta automaticamente un riferimento weak a `nil` quando l'istanza a cui fa riferimento viene deallocata. E, poiché i riferimenti weak devono consentire che il loro valore venga cambiato in `nil` in fase di esecuzione, vengono sempre dichiarati come variabili, anziché come costanti, di un tipo opzionale.

Puoi verificare la presenza di un valore nel riferimento weak, proprio come per qualsiasi altro valore opzionale, e non ti ritroverai mai con un riferimento a un'istanza non valida che non esiste più.

{% hint style="info" %}
**Nota:** Gli osservatori di proprietà non vengono chiamati quando ARC imposta un riferimento weak a `nil`.
{% endhint %}

L'esempio seguente è identico all'esempio `Person` e `Apartment` visto sopra, con una differenza importante. Questa volta, la proprietà `tenant` del tipo `Apartment` è dichiarata come riferimento weak:

```swift
class Person {
    let name: String
    init(name: String) { self.name = name }
    var apartment: Apartment?
    deinit { print("\(name) is being deinitialized") }
}

class Apartment {
    let unit: String
    init(unit: String) { self.unit = unit }
    weak var tenant: Person?
    deinit { print("Apartment \(unit) is being deinitialized") }
}
```

I riferimenti forti dalle due variabili (`john` e `unit4A`) e i collegamenti tra le due istanze vengono creati come prima:

```swift
var john: Person?
var unit4A: Apartment?

john = Person(name: "John Appleseed")
unit4A = Apartment(unit: "4A")

john!.apartment = unit4A
unit4A!.tenant = john
```

Ecco come appaiono i riferimenti ora che hai collegato le due istanze:

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

L'istanza di `Person` ha ancora un riferimento forte all'istanza di `Apartment`, ma l'istanza di `Apartment` ora ha un riferimento *weak* all'istanza di `Person`. Ciò significa che quando interrompi il riferimento forte mantenuto dalla variabile `john` impostandola a `nil`, non ci sono più riferimenti forti all'istanza di `Person`:

```swift
john = nil
// Stampa "John Appleseed is being deinitialized".
```

Poiché non ci sono più riferimenti forti all'istanza di `Person`, questa viene deallocata e la proprietà `tenant` viene impostata a `nil`:

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

L'unico riferimento forte rimasto all'istanza di `Apartment` proviene dalla variabile `unit4A`. Se interrompi *quel* riferimento forte, non ci sono più riferimenti forti all'istanza di `Apartment`:

```swift
unit4A = nil
// Stampa "Apartment 4A is being deinitialized".
```

Poiché non ci sono più riferimenti forti all'istanza di `Apartment`, anche questa viene deallocata:

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

{% hint style="info" %}
**Nota:** Nei sistemi che usano la garbage collection, i puntatori deboli vengono talvolta usati per implementare un semplice meccanismo di caching perché gli oggetti senza riferimenti forti vengono deallocati solo quando la pressione sulla memoria attiva la garbage collection. Tuttavia, con ARC, i valori vengono deallocati non appena il loro ultimo riferimento forte viene rimosso, il che rende i riferimenti weak inadatti a tale scopo.
{% endhint %}

### Riferimenti unowned <a href="#riferimenti-unowned" id="riferimenti-unowned"></a>

Come un riferimento weak, un *riferimento unowned* (non posseduto) non mantiene una presa forte sull'istanza a cui fa riferimento. A differenza di un riferimento weak, però, un riferimento unowned si usa quando l'altra istanza ha la stessa durata di vita o una durata di vita più lunga. Indichi un riferimento unowned collocando la parola chiave `unowned` prima della dichiarazione di una proprietà o di una variabile.

A differenza di un riferimento weak, ci si aspetta che un riferimento unowned abbia sempre un valore. Di conseguenza, contrassegnare un valore come unowned non lo rende opzionale, e ARC non imposta mai a `nil` il valore di un riferimento unowned.

{% hint style="warning" %}
**Importante:** Usa un riferimento unowned solo quando sei sicuro che il riferimento si riferisca *sempre* a un'istanza che non è stata deallocata.

Se provi ad accedere al valore di un riferimento unowned dopo che quell'istanza è stata deallocata, otterrai un errore in fase di esecuzione.
{% endhint %}

L'esempio seguente definisce due classi, `Customer` e `CreditCard`, che modellano un cliente di una banca e una possibile carta di credito per quel cliente. Queste due classi memorizzano ciascuna un'istanza dell'altra classe come proprietà. Questa relazione ha il potenziale di creare un ciclo di riferimenti forti.

La relazione tra `Customer` e `CreditCard` è leggermente diversa dalla relazione tra `Apartment` e `Person` vista nell'esempio sui riferimenti weak qui sopra. In questo modello di dati, un cliente può avere o non avere una carta di credito, ma una carta di credito sarà *sempre* associata a un cliente. Un'istanza di `CreditCard` non sopravvive mai al `Customer` a cui fa riferimento. Per rappresentare questo, la classe `Customer` ha una proprietà opzionale `card`, ma la classe `CreditCard` ha una proprietà `customer` unowned (e non opzionale).

Inoltre, una nuova istanza di `CreditCard` può essere creata *solo* passando un valore `number` e un'istanza `customer` a un inizializzatore personalizzato di `CreditCard`. Questo garantisce che un'istanza di `CreditCard` abbia sempre un'istanza `customer` associata quando l'istanza di `CreditCard` viene creata.

Poiché una carta di credito avrà sempre un cliente, definisci la sua proprietà `customer` come riferimento unowned, per evitare un ciclo di riferimenti forti:

```swift
class Customer {
    let name: String
    var card: CreditCard?
    init(name: String) {
        self.name = name
    }
    deinit { print("\(name) is being deinitialized") }
}

class CreditCard {
    let number: UInt64
    unowned let customer: Customer
    init(number: UInt64, customer: Customer) {
        self.number = number
        self.customer = customer
    }
    deinit { print("Card #\(number) is being deinitialized") }
}
```

{% hint style="info" %}
**Nota:** La proprietà `number` della classe `CreditCard` è definita con un tipo `UInt64` anziché `Int`, per garantire che la capacità della proprietà `number` sia abbastanza grande da memorizzare un numero di carta di 16 cifre sia sui sistemi a 32 bit sia su quelli a 64 bit.
{% endhint %}

Il frammento di codice successivo definisce una variabile `Customer` opzionale chiamata `john`, che verrà usata per memorizzare un riferimento a un cliente specifico. Questa variabile ha un valore iniziale di nil, in virtù del fatto di essere opzionale:

```swift
var john: Customer?
```

Ora puoi creare un'istanza di `Customer`, e usarla per inizializzare e assegnare una nuova istanza di `CreditCard` come proprietà `card` di quel cliente:

```swift
john = Customer(name: "John Appleseed")
john!.card = CreditCard(number: 1234_5678_9012_3456, customer: john!)
```

Ecco come appaiono i riferimenti, ora che hai collegato le due istanze:

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

L'istanza di `Customer` ora ha un riferimento forte all'istanza di `CreditCard`, e l'istanza di `CreditCard` ha un riferimento unowned all'istanza di `Customer`.

A causa del riferimento unowned `customer`, quando interrompi il riferimento forte mantenuto dalla variabile `john`, non ci sono più riferimenti forti all'istanza di `Customer`:

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

Poiché non ci sono più riferimenti forti all'istanza di `Customer`, questa viene deallocata. Dopo che ciò accade, non ci sono più riferimenti forti all'istanza di `CreditCard`, e anche questa viene deallocata:

```swift
john = nil
// Stampa "John Appleseed is being deinitialized".
// Stampa "Card #1234567890123456 is being deinitialized".
```

L'ultimo frammento di codice qui sopra mostra che i deinizializzatori dell'istanza di `Customer` e dell'istanza di `CreditCard` stampano entrambi i loro messaggi di “deinizializzazione” dopo che la variabile `john` è stata impostata a `nil`.

{% hint style="info" %}
**Nota:** Gli esempi qui sopra mostrano come usare riferimenti unowned *sicuri*. Swift fornisce anche riferimenti unowned *non sicuri* per i casi in cui hai bisogno di disabilitare i controlli di sicurezza in fase di esecuzione — per esempio, per ragioni di prestazioni. Come per tutte le operazioni non sicure, ti assumi la responsabilità di verificare la sicurezza di quel codice.

Indichi un riferimento unowned non sicuro scrivendo `unowned(unsafe)`. Se provi ad accedere a un riferimento unowned non sicuro dopo che l'istanza a cui fa riferimento è stata deallocata, il tuo programma tenterà di accedere alla posizione di memoria in cui si trovava l'istanza, il che è un'operazione non sicura.
{% endhint %}

### Riferimenti unowned opzionali <a href="#riferimenti-unowned-opzionali" id="riferimenti-unowned-opzionali"></a>

Puoi contrassegnare come unowned un riferimento opzionale a una classe. In termini di modello di possesso di ARC, un riferimento unowned opzionale e un riferimento weak possono essere usati entrambi negli stessi contesti. La differenza è che quando usi un riferimento unowned opzionale, sei responsabile di assicurarti che si riferisca sempre a un oggetto valido o che sia impostato a `nil`.

Ecco un esempio che tiene traccia dei corsi offerti da un particolare dipartimento di una scuola:

```swift
class Department {
    var name: String
    var courses: [Course]
    init(name: String) {
        self.name = name
        self.courses = []
    }
}

class Course {
    var name: String
    unowned var department: Department
    unowned var nextCourse: Course?
    init(name: String, in department: Department) {
        self.name = name
        self.department = department
        self.nextCourse = nil
    }
}
```

`Department` mantiene un riferimento forte a ciascun corso offerto dal dipartimento. Nel modello di possesso di ARC, un dipartimento possiede i suoi corsi. `Course` ha due riferimenti unowned, uno al dipartimento e uno al corso successivo che uno studente dovrebbe seguire; un corso non possiede nessuno di questi oggetti. Ogni corso fa parte di un qualche dipartimento quindi la proprietà `department` non è opzionale. Tuttavia, poiché alcuni corsi non hanno un corso successivo consigliato, la proprietà `nextCourse` è opzionale.

Ecco un esempio di utilizzo di queste classi:

```swift
let department = Department(name: "Horticulture")

let intro = Course(name: "Survey of Plants", in: department)
let intermediate = Course(name: "Growing Common Herbs", in: department)
let advanced = Course(name: "Caring for Tropical Plants", in: department)

intro.nextCourse = intermediate
intermediate.nextCourse = advanced
department.courses = [intro, intermediate, advanced]
```

Il codice qui sopra crea un dipartimento e i suoi tre corsi. I corsi introduttivo e intermedio hanno entrambi un corso successivo suggerito memorizzato nella loro proprietà `nextCourse`, che mantiene un riferimento unowned opzionale al corso che uno studente dovrebbe seguire dopo aver completato quello corrente.

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

Un riferimento unowned opzionale non mantiene una presa forte sull'istanza della classe che racchiude, e quindi non impedisce ad ARC di deallocare l'istanza. Si comporta come un riferimento unowned sotto ARC, tranne per il fatto che un riferimento unowned opzionale può essere `nil`.

Come per i riferimenti unowned non opzionali, sei responsabile di garantire che `nextCourse` si riferisca sempre a un corso che non è stato deallocato. In questo caso, per esempio, quando elimini un corso da `department.courses` devi anche rimuovere tutti i riferimenti a esso che altri corsi potrebbero avere.

{% hint style="info" %}
**Nota:** Il tipo sottostante di un valore opzionale è `Optional`, che è un'enumerazione della libreria standard di Swift. Tuttavia, gli opzionali sono un'eccezione alla regola secondo cui i tipi valore non possono essere contrassegnati con `unowned`.

L'opzionale che racchiude la classe non usa il conteggio dei riferimenti, quindi non hai bisogno di mantenere un riferimento forte all'opzionale.
{% endhint %}

### Riferimenti unowned e proprietà opzionali con unwrapping implicito <a href="#riferimenti-unowned-e-proprieta-opzionali-con-unwrapping-implicito" id="riferimenti-unowned-e-proprieta-opzionali-con-unwrapping-implicito"></a>

Gli esempi di riferimenti weak e unowned visti sopra coprono due degli scenari più comuni in cui è necessario interrompere un ciclo di riferimenti forti.

L'esempio `Person` e `Apartment` mostra una situazione in cui due proprietà, a entrambe le quali è consentito essere `nil`, hanno il potenziale di causare un ciclo di riferimenti forti. Questo scenario si risolve al meglio con un riferimento weak.

L'esempio `Customer` e `CreditCard` mostra una situazione in cui una proprietà a cui è consentito essere `nil` e un'altra proprietà che non può essere `nil` hanno il potenziale di causare un ciclo di riferimenti forti. Questo scenario si risolve al meglio con un riferimento unowned.

Tuttavia, esiste un terzo scenario, in cui *entrambe* le proprietà devono avere sempre un valore, e nessuna delle due proprietà deve mai essere `nil` una volta completata l'inizializzazione. In questo scenario, è utile combinare una proprietà unowned in una classe con una proprietà opzionale con unwrapping implicito nell'altra classe.

Questo permette di accedere direttamente a entrambe le proprietà (senza unwrapping dell'opzionale) una volta completata l'inizializzazione, evitando comunque un ciclo di riferimenti. Questa sezione ti mostra come impostare una relazione del genere.

L'esempio seguente definisce due classi, `Country` e `City`, ciascuna delle quali memorizza un'istanza dell'altra classe come proprietà. In questo modello di dati, ogni paese deve avere sempre una capitale, e ogni città deve appartenere sempre a un paese. Per rappresentare questo, la classe `Country` ha una proprietà `capitalCity`, e la classe `City` ha una proprietà `country`:

```swift
class Country {
    let name: String
    var capitalCity: City!
    init(name: String, capitalName: String) {
        self.name = name
        self.capitalCity = City(name: capitalName, country: self)
    }
}

class City {
    let name: String
    unowned let country: Country
    init(name: String, country: Country) {
        self.name = name
        self.country = country
    }
}
```

Per impostare l'interdipendenza tra le due classi, l'inizializzatore di `City` accetta un'istanza di `Country`, e memorizza questa istanza nella sua proprietà `country`.

L'inizializzatore di `City` viene chiamato dall'interno dell'inizializzatore di `Country`. Tuttavia, l'inizializzatore di `Country` non può passare `self` all'inizializzatore di `City` finché una nuova istanza di `Country` non è completamente inizializzata, come descritto in [Inizializzazione in due fasi](/guida-al-linguaggio/inizializzazione.md#inizializzazione-in-due-fasi).

Per far fronte a questo requisito, dichiari la proprietà `capitalCity` di `Country` come una proprietà opzionale con unwrapping implicito, indicata dal punto esclamativo alla fine della sua annotazione di tipo (`City!`). Ciò significa che la proprietà `capitalCity` ha un valore predefinito di `nil`, come qualsiasi altro opzionale, ma vi si può accedere senza bisogno di fare l'unwrapping del suo valore, come descritto in [Opzionali con unwrapping implicito](/guida-al-linguaggio/le-basi.md#opzionali-con-unwrapping-implicito).

Poiché `capitalCity` ha un valore predefinito `nil`, una nuova istanza di `Country` è considerata completamente inizializzata non appena l'istanza di `Country` imposta la sua proprietà `name` all'interno del suo inizializzatore. Ciò significa che l'inizializzatore di `Country` può iniziare a fare riferimento alla proprietà implicita `self` e a passarla ad altri non appena la proprietà `name` è impostata. L'inizializzatore di `Country` può quindi passare `self` come uno dei parametri dell'inizializzatore di `City` quando l'inizializzatore di `Country` imposta la propria proprietà `capitalCity`.

Tutto ciò significa che puoi creare le istanze di `Country` e di `City` in un'unica istruzione, senza creare un ciclo di riferimenti forti, e si può accedere direttamente alla proprietà `capitalCity`, senza bisogno di usare un punto esclamativo per fare l'unwrapping del suo valore opzionale:

```swift
var country = Country(name: "Canada", capitalName: "Ottawa")
print("\(country.name)'s capital city is called \(country.capitalCity.name)")
// Stampa "Canada's capital city is called Ottawa".
```

Nell'esempio qui sopra, l'uso di un opzionale con unwrapping implicito fa sì che tutti i requisiti dell'inizializzatore di classe in due fasi siano soddisfatti. La proprietà `capitalCity` può essere usata e acceduta come un valore non opzionale una volta completata l'inizializzazione, evitando comunque un ciclo di riferimenti forti.

## Cicli di riferimenti forti per le closure <a href="#cicli-di-riferimenti-forti-per-le-closure" id="cicli-di-riferimenti-forti-per-le-closure"></a>

Hai visto sopra come si possa creare un ciclo di riferimenti forti quando due proprietà di istanze di classe mantengono un riferimento forte l'una all'altra. Hai visto anche come usare i riferimenti weak e unowned per interrompere questi cicli di riferimenti forti.

Un ciclo di riferimenti forti può verificarsi anche se assegni una closure a una proprietà di un'istanza di classe, e il corpo di quella closure cattura l'istanza. Questa cattura potrebbe verificarsi perché il corpo della closure accede a una proprietà dell'istanza, come `self.someProperty`, o perché la closure chiama un metodo sull'istanza, come `self.someMethod()`. In entrambi i casi, questi accessi fanno sì che la closure “catturi” `self`, creando un ciclo di riferimenti forti.

Questo ciclo di riferimenti forti si verifica perché le closure, come le classi, sono *tipi riferimento*. Quando assegni una closure a una proprietà, stai assegnando un *riferimento* a quella closure. In sostanza, è lo stesso problema di prima — due riferimenti forti si mantengono in vita a vicenda. Tuttavia, anziché due istanze di classe, questa volta sono un'istanza di classe e una closure a mantenersi in vita a vicenda.

Swift fornisce una soluzione elegante a questo problema, nota come *lista di cattura della closure*. Tuttavia, prima di imparare a interrompere un ciclo di riferimenti forti con una lista di cattura, è utile capire come si possa originare un ciclo del genere.

L'esempio seguente mostra come puoi creare un ciclo di riferimenti forti quando usi una closure che fa riferimento a `self`. Questo esempio definisce una classe chiamata `HTMLElement`, che fornisce un semplice modello per un singolo elemento all'interno di un documento HTML:

```swift
class HTMLElement {
    let name: String
    let text: String?

    lazy var asHTML: () -> String = {
        if let text = self.text {
            return "<\(self.name)>\(text)</\(self.name)>"
        } else {
            return "<\(self.name) />"
        }
    }

    init(name: String, text: String? = nil) {
        self.name = name
        self.text = text
    }

    deinit {
        print("\(name) is being deinitialized")
    }
}
```

La classe `HTMLElement` definisce una proprietà `name`, che indica il nome dell'elemento, come `"h1"` per un elemento di intestazione, `"p"` per un elemento paragrafo, o `"br"` per un elemento di interruzione di riga. `HTMLElement` definisce anche una proprietà opzionale `text`, che puoi impostare a una stringa che rappresenta il testo da visualizzare all'interno di quell'elemento HTML.

Oltre a queste due semplici proprietà, la classe `HTMLElement` definisce una proprietà lazy chiamata `asHTML`. Questa proprietà fa riferimento a una closure che combina `name` e `text` in un frammento di stringa HTML. La proprietà `asHTML` è di tipo `() -> String`, ovvero “una funzione che non accetta parametri e restituisce un valore `String`”.

Per impostazione predefinita, alla proprietà `asHTML` viene assegnata una closure che restituisce una rappresentazione in forma di stringa di un tag HTML. Questo tag contiene il valore opzionale `text` se esiste, oppure nessun contenuto testuale se `text` non esiste. Per un elemento paragrafo, la closure restituirebbe `"<p>some text</p>"` o `"<p />"`, a seconda che la proprietà `text` sia uguale a `"some text"` o a `nil`.

La proprietà `asHTML` è denominata e usata in modo un po' simile a un metodo di istanza. Tuttavia, poiché `asHTML` è una proprietà closure anziché un metodo di istanza, puoi sostituire il valore predefinito della proprietà `asHTML` con una closure personalizzata, se vuoi cambiare la resa HTML per un particolare elemento HTML.

Per esempio, la proprietà `asHTML` potrebbe essere impostata a una closure che usa un testo predefinito se la proprietà `text` è `nil`, per evitare che la rappresentazione restituisca un tag HTML vuoto:

```swift
let heading = HTMLElement(name: "h1")
let defaultText = "some default text"
heading.asHTML = {
    return "<\(heading.name)>\(heading.text ?? defaultText)</\(heading.name)>"
}
print(heading.asHTML())
// Stampa "<h1>some default text</h1>".
```

{% hint style="info" %}
**Nota:** La proprietà `asHTML` è dichiarata come proprietà lazy, perché serve solo se e quando l'elemento deve effettivamente essere reso come valore stringa per una qualche destinazione di output HTML. Il fatto che `asHTML` sia una proprietà lazy significa che puoi fare riferimento a `self` all'interno della closure predefinita, perché alla proprietà lazy non si accederà fino a dopo che l'inizializzazione è stata completata e si sa che `self` esiste.
{% endhint %}

La classe `HTMLElement` fornisce un unico inizializzatore, che accetta un argomento `name` e (se desiderato) un argomento `text` per inizializzare un nuovo elemento. La classe definisce anche un deinizializzatore, che stampa un messaggio per mostrare quando un'istanza di `HTMLElement` viene deallocata.

Ecco come usi la classe `HTMLElement` per creare e stampare una nuova istanza:

```swift
var paragraph: HTMLElement? = HTMLElement(name: "p", text: "hello, world")
print(paragraph!.asHTML())
// Stampa "<p>hello, world</p>".
```

{% hint style="info" %}
**Nota:** La variabile `paragraph` qui sopra è definita come `HTMLElement` *opzionale*, in modo che possa essere impostata a `nil` più avanti per dimostrare la presenza di un ciclo di riferimenti forti.
{% endhint %}

Purtroppo, la classe `HTMLElement`, così come è scritta sopra, crea un ciclo di riferimenti forti tra un'istanza di `HTMLElement` e la closure usata per il suo valore predefinito di `asHTML`. Ecco come appare il ciclo:

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

La proprietà `asHTML` dell'istanza mantiene un riferimento forte alla sua closure. Tuttavia, poiché la closure fa riferimento a `self` all'interno del suo corpo (come modo per fare riferimento a `self.name` e `self.text`), la closure *cattura* self, il che significa che mantiene a sua volta un riferimento forte all'istanza di `HTMLElement`. Tra le due si crea un ciclo di riferimenti forti. (Per maggiori informazioni sulla cattura di valori in una closure, vedi [Catturare valori](/guida-al-linguaggio/closure.md#catturare-valori).)

{% hint style="info" %}
**Nota:** Anche se la closure fa riferimento a `self` più volte, cattura un solo riferimento forte all'istanza di `HTMLElement`.
{% endhint %}

Se imposti la variabile `paragraph` a `nil` e interrompi il suo riferimento forte all'istanza di `HTMLElement`, il ciclo di riferimenti forti impedisce di deallocare sia l'istanza di `HTMLElement` sia la sua closure:

```swift
paragraph = nil
```

Nota che il messaggio del deinizializzatore di `HTMLElement` non viene stampato, il che dimostra che l'istanza di `HTMLElement` non viene deallocata.

## Risolvere i cicli di riferimenti forti per le closure <a href="#risolvere-i-cicli-di-riferimenti-forti-per-le-closure" id="risolvere-i-cicli-di-riferimenti-forti-per-le-closure"></a>

Risolvi un ciclo di riferimenti forti tra una closure e un'istanza di classe definendo una *lista di cattura* come parte della definizione della closure. Una lista di cattura definisce le regole da usare quando si catturano uno o più tipi riferimento all'interno del corpo della closure. Come per i cicli di riferimenti forti tra due istanze di classe, dichiari ciascun riferimento catturato come riferimento weak o unowned anziché come riferimento forte. La scelta appropriata tra weak e unowned dipende dalle relazioni tra le diverse parti del tuo codice.

{% hint style="info" %}
**Nota:** Swift ti richiede di scrivere `self.someProperty` o `self.someMethod()` (anziché semplicemente `someProperty` o `someMethod()`) ogni volta che fai riferimento a un membro di `self` all'interno di una closure. Questo ti aiuta a ricordare che è possibile catturare `self` per errore.
{% endhint %}

### Definire una lista di cattura <a href="#definire-una-lista-di-cattura" id="definire-una-lista-di-cattura"></a>

Ogni elemento di una lista di cattura è l'abbinamento della parola chiave `weak` o `unowned` con un riferimento a un'istanza di classe (come `self`) o con una variabile inizializzata con un certo valore (come `delegate = self.delegate`). Questi abbinamenti si scrivono all'interno di una coppia di parentesi quadre, separati da virgole.

Colloca la lista di cattura prima dell'elenco dei parametri e del tipo di ritorno di una closure, se sono forniti:

```swift
lazy var someClosure = {
        [unowned self, weak delegate = self.delegate]
        (index: Int, stringToProcess: String) -> String in
    // qui va il corpo della closure
}
```

Se una closure non specifica un elenco di parametri o un tipo di ritorno perché possono essere inferiti dal contesto, colloca la lista di cattura proprio all'inizio della closure, seguita dalla parola chiave `in`:

```swift
lazy var someClosure = {
        [unowned self, weak delegate = self.delegate] in
    // qui va il corpo della closure
}
```

### Riferimenti weak e unowned <a href="#riferimenti-weak-e-unowned" id="riferimenti-weak-e-unowned"></a>

Definisci una cattura in una closure come riferimento unowned quando la closure e l'istanza che cattura faranno sempre riferimento l'una all'altra, e verranno sempre deallocate nello stesso momento.

Al contrario, definisci una cattura come riferimento weak quando il riferimento catturato potrebbe diventare `nil` in futuro. I riferimenti weak sono sempre di un tipo opzionale, e diventano automaticamente `nil` quando l'istanza a cui fanno riferimento viene deallocata. Questo ti permette di verificarne l'esistenza all'interno del corpo della closure.

{% hint style="info" %}
**Nota:** Se il riferimento catturato non diventerà mai `nil`, dovrebbe sempre essere catturato come riferimento unowned, anziché come riferimento weak.
{% endhint %}

Un riferimento unowned è il metodo di cattura appropriato da usare per risolvere il ciclo di riferimenti forti nell'esempio `HTMLElement` di [Cicli di riferimenti forti per le closure](/guida-al-linguaggio/conteggio-automatico-dei-riferimenti.md#cicli-di-riferimenti-forti-per-le-closure) visto sopra. Ecco come scrivi la classe `HTMLElement` per evitare il ciclo:

```swift
class HTMLElement {
    let name: String
    let text: String?

    lazy var asHTML: () -> String = {
            [unowned self] in
        if let text = self.text {
            return "<\(self.name)>\(text)</\(self.name)>"
        } else {
            return "<\(self.name) />"
        }
    }

    init(name: String, text: String? = nil) {
        self.name = name
        self.text = text
    }

    deinit {
        print("\(name) is being deinitialized")
    }
}
```

Questa implementazione di `HTMLElement` è identica all'implementazione precedente, a parte l'aggiunta di una lista di cattura all'interno della closure `asHTML`. In questo caso, la lista di cattura è `[unowned self]`, che significa “cattura self come riferimento unowned anziché come riferimento forte”.

Puoi creare e stampare un'istanza di `HTMLElement` come prima:

```swift
var paragraph: HTMLElement? = HTMLElement(name: "p", text: "hello, world")
print(paragraph!.asHTML())
// Stampa "<p>hello, world</p>".
```

Ecco come appaiono i riferimenti con la lista di cattura in uso:

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

Questa volta, la cattura di `self` da parte della closure è un riferimento unowned, e non mantiene una presa forte sull'istanza di `HTMLElement` che ha catturato. Se imposti a `nil` il riferimento forte dalla variabile `paragraph`, l'istanza di `HTMLElement` viene deallocata, come si può vedere dalla stampa del messaggio del suo deinizializzatore nell'esempio seguente:

```swift
paragraph = nil
// Stampa "p is being deinitialized".
```

Per maggiori informazioni sulle liste di cattura, vedi [Liste di cattura](/riferimento-del-linguaggio/espressioni.md#liste-di-cattura).
