Ho appena terminato il debug di una perdita molto fastidiosa di UIViewController
, in modo tale che UIViewController non è stato deallocato anche dopo aver chiamato dismissViewControllerAnimated
.Perché un riferimento forte al controllore UIViewController in performBatchUpdates perde un'attività?
ho rintracciato il problema al seguente blocco di codice:
self.dataSource.doNotAllowUpdates = YES;
[self.collectionView performBatchUpdates:^{
[self.collectionView reloadItemsAtIndexPaths:@[indexPath]];
} completion:^(BOOL finished) {
self.dataSource.doNotAllowUpdates = NO;
}];
In sostanza, se faccio una chiamata a performBatchUpdates
e poi subito chiamare dismissViewControllerAnimated
, l'UIViewController viene perdeva e il metodo di che UIViewController
dealloc
mai viene chiamato Il controllore UIView è in agguato per sempre.
Qualcuno può spiegare questo comportamento? Presumo che performBatchUpdates
venga eseguito su un intervallo di tempo, ad esempio 500 ms, quindi suppongo che dopo detto intervallo, chiamerà questi metodi e quindi attiverà il dealloc.
La correzione sembra essere questo:
self.dataSource.doNotAllowUpdates = YES;
__weak __typeof(self)weakSelf = self;
[self.collectionView performBatchUpdates:^{
__strong __typeof(weakSelf)strongSelf = weakSelf;
if (strongSelf) {
[strongSelf.collectionView reloadItemsAtIndexPaths:@[indexPath]];
}
} completion:^(BOOL finished) {
__strong __typeof(weakSelf)strongSelf = weakSelf;
if (strongSelf) {
strongSelf.dataSource.doNotAllowUpdates = NO;
}
}];
nota che la variabile BOOL
membro, doNotAllowUpdates
, è una variabile ho aggiunto che impedisce qualsiasi tipo di aggiornamenti dataSource/CollectionView mentre una chiamata a performBatchUpdates è in esecuzione.
Ho cercato in giro per discussioni online sull'opportunità o meno di utilizzare il modello weakSelf/strongSelf in performBatchUpdates
, ma non ho trovato nulla di specifico su questa domanda.
Sono felice di essere stato in grado di arrivare in fondo a questo bug, ma mi piacerebbe uno sviluppatore iOS più intelligente per spiegarmi questo comportamento che sto vedendo.
Sarebbe interessante vedere se è possibile risolvere se si trattasse del blocco degli aggiornamenti o del blocco di completamento che stava causando il ciclo di conservazione. Come dici tu, nessuno dei due dovrebbe rimanere permanentemente al loro blocco: posso solo supporre che quando la vista raccolta viene rimossa dalla sua superview, smetta di eseguire qualsiasi aggiornamento in batch e non chiami o rilasci il blocco di completamento. Merita un radar secondo me. – jrturton
@jrturton Ahh questa sembra la spiegazione più probabile! Vedrò se posso riproporlo nel debugger basato su questa intuizione. – esilver
@jrturton ahimè non è in grado di eseguire la repro nel debugger ... sembra che entrambi i blocchi, almeno, vengano sempre chiamati. Forse gli interni non hanno nulla a che fare con i blocchi, anche se il rigore viene chiamato nel mezzo? – esilver