2014-09-22 15 views
10

Sto cercando di risolvere un ciclo di riferimento forte basato sulla chiusura in Swift.
Nel codice sottostante, l'oggetto viene mantenuto dal controller di visualizzazione proprietario. ProgressHUD è un UIView che viene mantenuto anche dal controller di visualizzazione proprietario. ProgressHUD viene interrotto ogni volta che viene chiamato il gestore di completamento. Quando si utilizza la nuova funzionalità di cattura di chiusura, dichiarare se stesso come debole o non proprietario non risolve la perdita di memoria.Chiusure Swift - Catturare sé come debole

object.setCompletionHandler { [weak self] (error) -> Void in 
    if(!error){ 
     self?.tableView.reloadData() 
    } 
    self?.progressHUD?.hide(false) 
} 

Tuttavia, se dichiaro debole var per l'auto al di fuori della chiusura, si risolve la perdita di memoria, in questo modo:

weak var weakSelf = self 
object.setCompletionHandler { (error) -> Void in 
    if(!error){ 
     weakSelf?.tableView.reloadData() 
    } 
    weakSelf?.progressHUD?.hide(false) 
} 

Tutte le idee perché questo non funziona con la cattura Swift ?

+0

non ci dovrebbe essere un ciclo conservano – newacct

risposta

-3

provare quanto segue:

object.setCompletionHandler { [unowned self] (error) ->() in 
    if(!error){ 
     weakSelf?.tableView.reloadData() 
    } 
    weakSelf?.progressHUD?.hide(false) 
} 
+0

come notato nel post originale, né deboli o senza proprietario risolve perdita di memoria. Grazie comunque. –

11

Se si assegna una chiusura a una proprietà di un'istanza di classe, e la chiusura cattura tale istanza facendo riferimento all'istanza o ai suoi membri, si creerà un ciclo di riferimento forte tra la chiusura e l'istanza. Swift utilizza gli elenchi di acquisizione per interrompere questi forti cicli di riferimento. source Apple

source sketchyTech In primo luogo, è importante chiarire che l'intera questione riguarda soltanto le chiusure dove stiamo assegnando "una chiusura a una proprietà di un'istanza di classe". Tienilo a mente con ogni regola. Le regole:

  1. uso cattura debole se l'istanza di classe o di proprietà è un optional
  2. uso senza proprietario se l'istanza di classe o struttura è per non facoltativo e non possono mai essere impostati a zero
  3. "è necessario ... usa la parola chiave in, anche se ometti i nomi dei parametri, i tipi di parametri e il tipo di reso "

In risposta alla tua domanda non ci dovrebbe essere alcun ciclo di conservazione.

4

Lei ha affermato che progressHUD è trattenuta dal controller della vista possessore (auto) e si fa riferimento nella vostra chiusura ... quindi aggiungerlo alla lista di cattura e quindi utilizzare la variabile catturato nella chiusura come segue:

object.setCompletionHandler { [weak self] (error) -> Void in 
    if(!error){ 
     self?.tableView.reloadData() 
    } 
    self?.progressHUD.hide(false) 
} 
+0

I riferimenti noti vengono involontariamente scartati, quindi 'self? .tableView' deve essere cambiato in' self.tableView'. –

+0

sei corretto @zxzxlch, ho modificato la mia soluzione cambiando il sé sconosciuto fino a indebolire te stesso e lasciando cadere progressHUD dalla lista di cattura. Non ci dovrebbe essere alcun ciclo di conservazione. – dferrero

-1

Questo è il modo che ho fatto è:

object.setCompletionHandler { [weak self] (error) -> Void in 
    if let weakSelf = self { 
     if (!error) { 
      weakSelf.tableView.reloadData() 
     } 

     weakSelf.progressHUD?.hide(false) 
    } 
} 
+3

Questo è esattamente all'indietro. Rinominare 'weakSelf' in 'strongSelf'. Il "let" ti dà un forte riferimento. –

Problemi correlati