Il pattern di delega (delegation) è uno dei principali nel sistema Swift, ampiamente utilizzato per trasferire la responsabilità nella gestione degli eventi tra oggetti. La delega consente a una classe di delegare una parte del suo comportamento a un altro oggetto (delegato), definito, in genere, tramite un protocollo.
protocol DataUpdateDelegate: AnyObject { func didUpdateData(_ data: String) } class DataProvider { weak var delegate: DataUpdateDelegate? func updateData() { // ... logica di aggiornamento dei dati delegate?.didUpdateData("Nuovi dati") } } class ViewController: UIViewController, DataUpdateDelegate { func didUpdateData(_ data: String) { print("Dati aggiornati: \(data)") } }
weak (o unowned), per evitare cicli di retain.AnyObject, per consentire riferimenti weak.Come implementeresti la delega se il tuo delegato è un tipo value (ad esempio, struct)?
Risposta:
In Swift, i delegati devono essere tipi di riferimento (class o AnyObject), poiché solo i tipi di riferimento possono avere riferimenti weak. Un delegato non può essere una struct o un enum, altrimenti si verificherebbero problemi: il compilatore non consentirebbe l'uso di una proprietà weak, mentre un riferimento strong porterebbe a un ciclo di retain.
// Errore! Non è possibile dichiarare un delegato come struct: il compilatore non permetterà di renderlo weak protocol StructDelegate { ... } struct MyStructDelegate: StructDelegate { ... } weak var delegate: StructDelegate? // Errore
Storia
In un progetto, è stato dimenticato di contrassegnare la proprietà del delegato come weak. Di conseguenza, si è verificato un ciclo di retain tra view e delegato, l'app ha cominciato a "gonfiarsi" in termini di memoria e si è bloccata dopo mezz'ora di funzionamento.
Storia
Il delegato è stato implementato tramite un tipo value (struct), invece di una classe. L'IBOutlet, che avrebbe dovuto essere il delegato, non riceveva notifiche — non si verificava alcuna connessione. Il problema è stato scoperto solo dopo l'analisi dei log e il debug.
Storia
Nel progetto, il protocollo del delegato non ereditava da AnyObject, e la proprietà del delegato è stata dichiarata come weak var. Questo ha portato a un errore di compilazione, che ha richiesto tempo al team per capire e correggere.