Rappelez-vous aussi que de conserver les cycles peuvent se produire si votre bloc fait référence à un autre objet qui conserve alors self
.
Je ne suis pas sûr que la Collecte des Ordures peut aider à conserver ces cycles. Si l'objet en conservant le bloc (que je vais appeler le serveur de l'objet) survit self
(le client de l'objet), la référence à l' self
à l'intérieur du bloc ne sera pas considéré comme cyclique jusqu'à ce que le maintien de l'objet lui-même est libéré. Si le serveur de l'objet de la mesure survit à ses clients, vous pouvez avoir une fuite de mémoire importante.
Puisqu'il n'existe pas de solutions propres, je vous recommande les solutions de contournement suivantes. N'hésitez pas à choisir l'un ou plusieurs d'entre eux afin de résoudre votre problème.
- L'utilisation de blocs seulement pour l'achèvement, et pas pour ouvert événements. Par exemple, l'utilisation de blocs de méthodes comme l'
doSomethingAndWhenDoneExecuteThisBlock:
, et non pas des méthodes comme setNotificationHandlerBlock:
. Les blocs utilisés pour la réalisation ont des extrémités de la vie, et il doit être libéré par le serveur, les objets une fois qu'ils sont évalués. Cela empêche le conserver cycle de vie depuis trop longtemps, même si elle se produit.
- Faire que la faiblesse de référence de la danse que vous avez décrit.
- Fournir une méthode pour nettoyer votre objet avant qu'il soit libéré, qui "déconnecte" de l'objet à partir du serveur d'objets qui peuvent contenir des références à elle; et cette méthode est appelée avant l'appel à la libération de l'objet. Bien que cette méthode est parfaitement bien si votre objet n'a qu'un seul client (ou est un singleton dans un certain contexte), mais briser si l'on a plusieurs clients. Vous êtes essentiellement en battant le conserver-mécanisme de comptage ici; cela ressemble à l'appel
dealloc
au lieu de release
.
Si vous êtes à la rédaction d'un objet serveur, prendre en bloc les arguments que pour l'achèvement. Ne pas accepter en bloc les arguments pour les rappels, comme setEventHandlerBlock:
. Au lieu de cela, revenir à la classique modèle délégué: créer un protocole formel, et de la publicité d'un setEventDelegate:
méthode. Ne pas conserver le délégué. Si vous ne voulez même pas à créer un protocole formel, accepter un sélecteur en tant que délégué de rappel.
Et enfin, ce modèle devrait sonner des alarmes:
- (void)dealloc {
[myServerObject releaseCallbackBlocksForObject:self];
...
}
Si vous êtes en essayant de détacher les blocs qui peuvent se référer à des self
depuis l'intérieur d' dealloc
, vous êtes déjà en difficulté. dealloc
ne peut jamais être appelé en raison de la conserver cycle causés par des références dans le bloc, ce qui signifie que votre objet est simplement de fuite jusqu'à ce que l'objet serveur est libéré.