Skip to content

Utilizzare le WeakRef

In tutti i linguaggi ad oggetti è facile far riferimenti incrociati tra gli oggetti. Ma se non si presta attenzione si possono incontrare problemi importanti ed inaspettati.

L’esempio più banale e tipico è utilizzare una finestra per modificare alcune cose in un’altra.

Poniamo di avere una finestra di servizio (winCambiaTitolo) che viene aperta da una finestra. Nella winCambiaTitolo abbiamo un pulsante che permette di aggiungere un carattere al titolo della finestra chiamante. Per assegnare la finestra chiamante abbiamo una proprietà che chiamiamo finestra.

Se questa proprietà è di tipo window può succedere che diciamo dalla window1 di aprire winCambiaTitolo e assegnamo self alla proprietà finestra di winCambiaTitolo

//Pulsante su window1
dim w as new winCambiaTitolo
w.finestra = self
 
//Pulsante su winCambiaTitolo
finestra.titolo = finestra.titolo + "*"

Premendo il pulsante su Window1 e poi sulla nuova winCambiaTitolo vediamo cambiare il titolo di window1. Tutto ok.

Ma se chiudo la window1, questa non appare più ma in realtà non viene rilasciata perchè la proprietà finestra fa riferimento a questo oggetto. Questa è una conseguenza dell’ Automatic Reference Count per cui:

Azione Contatore ARC
di Window1
Apro window1 1
Assegno window1 alla proprietà di window2 2
Chiudo window1 1

Quindi l’oggetto è in realtà ancora in memoria.

Per risolvere questo basta dichiarare la proprietà finestra come WeakRef (riferimento debole). Un riferimento debole non increamenta i contatori ARC e la window1 viene rilasciata correttamente quando viene chiusa.

Il codice deve quindi diventare:

//Pulsante su window1
dim w as new winCambiaTitolo
w.finestra = new WeakRef(self)
 
//Pulsante su winCambiaTitolo
if finestra.value<>nil then
    window(finestra.value).title = window(finestra.value).title + "*"
end if

In questo modo non abbiamo MemoryLeak (ovvero oggetti che occupano memoria ma non sono più raggiungibili) ma ovviamente dobbiamo fare il casting (indicare il tipo) del puntatore rappresentato dalla WeakRef (essendo un puntatore non abbiamo idea dell’oggetto originale)