ARC (Automatic Reference Counting) — sistema di gestione automatica della memoria in Swift. Ad ogni nuovo puntatore forte a un oggetto, il conteggio aumenta; quando viene rimosso, diminuisce. Quando il conteggio è zero, l'oggetto viene liberato.
Ciclo di mantenimento (retain cycle) — situazione in cui gli oggetti si riferiscono l'uno all'altro tramite riferimenti forti e non vengono mai liberati.
Modi per evitarlo:
protocol SomeDelegate: AnyObject { } class Owner { weak var delegate: SomeDelegate? }
[weak self] o [unowned self]:class Example { var closure: (() -> Void)? func setup() { closure = { [weak self] in self?.doSomething() } } func doSomething() { } }
Qual è la differenza tra [weak self] e [unowned self] all'interno di una closure? Quale tipo di riferimento utilizzare e quando?
Risposta:
[weak self] crea un riferimento opzionale; self può essere nil, quindi di solito si utilizza il recupero sicuro self?.[unowned self] crea un riferimento non opzionale e NON aumenta il conteggio; se l'oggetto è già stato liberato e si verifica un accesso — si verificherà un crash.[unowned self].Esempio:
someClosure = { [weak self] in self?.doTask() } // oppure (se self vive al 100% più a lungo della closure): someClosure = { [unowned self] in doTask() }
Storia
Nel progetto si è verificata una situazione di cicli di mantenimento tra ViewController e la sua closure legata alla gestione dei tocchi. ViewController si riferiva alla closure, che catturava self tramite riferimento forte. Di conseguenza, il controller e tutti i suoi dati non venivano liberati dopo la chiusura dello schermo. Il problema è stato risolto implementando
[weak self]nella closure.
Storia
Implementazione del pattern delegato tra due oggetti. Il delegato è stato dichiarato come proprietà forte (
strong). Di conseguenza, quando si tentava di rimuovere l'oggetto principale dalla memoria, non veniva deallocato, portando a una fuga di memoria. Dopo aver spostato il delegato su weak, il problema è scomparso.
Storia
Per l'animazione è stata utilizzata una closure all'interno di UIView. La closure catturava self con
[unowned self]. Quando le viste venivano rimosse prima del completamento dell'animazione, l'app si chiudeva a causa di un accesso a self già liberato. La soluzione — utilizzo di[weak self]e verifica obbligatoria su self non nil all'interno della closure.