Les delegates d'object système dans ARC doivent-ils être définis sur zéro?

Une application se bloque parfois avec l'erreur objc_object::release() .

Le support technique Apple Developer a mentionné ceci:

Rappelez-vous que vous devriez toujours faire quelque chose comme _tableView.delegate = nil; dans vos methods -dealloc, même si vous utilisez ARC. Pour des raisons de compatibilité, les objects système utilisent des references unsafe_unretained pour implémenter la délégation, au lieu du weak rlocation préféré préféré.

Cela signifie-t-il que je dois mettre les delegates des objects système à zéro quand le controller de vue est sur le point d'être libéré?

 class MyViewController: UIViewController { deinit { tableView.delegate = nil tableView.dataSource = nil } } 

J'ai toujours supposé UITableView et les objects standard similaires utilisent weak references weak à leurs delegates?


Mettre à jour:

Il semble que l'exemple du support technique était obsolète car UITableView a déjà été mis à jour pour un weak délégué. Cependant, tous les delegates n'ont pas été mis à jour, par exemple AVAudioPlayer.delegate n'a toujours pas été unowned(unsafe) . Il semble qu'Apple met graduellement à jour les delegates pour qu'ils soient weak .

Pour déterminer si un délégué a été défini à zéro manuellement peut simplement être déterminé en inspectant la déclaration de délégué dans Xcode. Si c'est weak , ne vous embêtez pas.

Oui, vous devriez mettre ces delegates à nil .

Comme suggéré par le nom, les references unsafe_unretained ne conservent pas votre controller de vue, donc il n'y a pas de cycle de conservation ou de fuite de memory ici. Cependant, contrairement à weak , ces references ne seront pas définies automatiquement lorsque votre controller de vue est désalloué. Dans la plupart des cas, cela ne pose aucun problème car votre controller de vues survivra à ses vues ou, au less, sera désalloué en même time. Malheureusement, il y a quelques cas où UIKit peut avoir temporairement conservé la vue. Cela peut permettre à la vue de survivre au controller de vue et tenter d'appeler des methods déléguées sur l'object désalloué entraînant un blocage.

Le moyen le plus simple que je connaisse pour voir ceci en action est de rejeter et de désallouer un controller de vue qui est un délégué d'une vue déroulante (ou une de ses sous-classs comme UITableView) pendant que le défilement défile encore (par exemple une longue list d'articles). La vue de défilement scrollViewDidScroll alors d'appeler des methods de délégué (comme scrollViewDidScroll ) sur le controller scrollViewDidScroll .