Sto lavorando con le classi di richieste di rete e sono preoccupato per gli arresti . Ad esempio, lavorando con chiusure è molto facile come si passa un metodo di callback per una funzione:Closures vs Delegate pattern
// some network client
func executeHttpRequest(#callback: (success: Bool) -> Void) {
// http request
callback(true)
}
// View Controller
func reload() {
networkClient.executeHttpRequest() { (success) -> Void in
self.myLabel.text = "it succeeded" // NOTE THIS CALL
}
}
Tuttavia, poiché il processo che deve eseguire il callback è asincrona, quando callback interagiscono con elemento classe contenitore (in questo caso un UIKit
classe) può essere vulnerabile a crash in situazioni come
- l'utente navigato a un altro controller di vista, mentre il compito asincrono era ancora in esecuzione
- l'utente ha premuto il pulsante di casa, mentre il compito asincrono era ancora in esecuzione
- Etc ...
Così, quando il callback finalmente viene licenziato, self.myLabel.text
potrebbe risultare in un incidente, come il controller della vista a cui self
riferivo potrebbe già essere deallocato.
Fino a questo punto. Ho ragione o implemento rapidamente qualcosa internamente in modo che non accada mai?
Se ho ragione, ecco quando lo schema dei delegati è utile, poiché le variabili delegate sono weak references
, il che significa che non vengono mantenute in memoria se deallocate.
// some network client
// NOTE this variable is an OPTIONAL and it's also a WEAK REFERENCE
weak var delegate: NetworkClientDelegate?
func executeHttpRequest() {
// http request
if let delegate = self.delegate {
delegate.callback(success: true)
}
}
Si noti come self.delegate
, dal momento che è un weak reference
, punterà al nil
se il regolatore View (che implementa il protocollo NetworkClientDelegate
) viene deallocato, e la richiamata non è chiamato in questo caso.
La mia domanda sarebbe: le chiusure hanno qualcosa di speciale che le rende una buona scelta in scenari simili a questo, piuttosto che tornare a delegare lo schema? Sarebbe bene se vengono forniti esempi di chiusure (che non finiranno in arresti anomali dovuti al puntatore nullo). Grazie.
Bene, il primo non si arresta in modo anomalo, poiché il riferimento a se stesso nel blocco impedisce di essere deallocato mentre il blocco è ancora attivo. – dan
Piccolo suggerimento Swift: usa 'delegate? .callback (success: true)' invece di 'se let delegate = self.delegate {delegate.callback (success: true)}'. Inoltre non avresti bisogno del 'self' per accedere a una proprietà;) – Kametrixom