NSOperation et retain du delegate

colionelcolionel Membre
14:58 modifié dans API AppKit #1
Salut,

Je cherche une bonne pratique sur la gestion mémoire des delegate en multi-thread.

D'ordinaire mes delegate sont en assign :

@property (nonatomic, assign) id delegate;

Mais dans le cas d'une NSOperation ça me donne des résultats étrange : je perd la référence vers mon delegate et je récupère des EXC_BAD_ACCESS

J'ai remarqué que tout rentrait dans l'ordre si je faisais un retain sur mon delegate :

@property (nonatomic, retain) id delegate;

Est ce que quelqu'un pourrait éclairer ma lanterne ?

P.S: Dans les docs d'apple je n'ai trouvé que des références à  "Delegating objects do not (and should not) retain their delegates."

Merci,
Vincent.

Réponses

  • AliGatorAliGator Membre, Modérateur
    14:58 modifié #2
    En effet les delegate sont en général en assign surtout pour éviter les "retain cycles" et parce que ce sont des délégués, informés, tu n'es pas sensé être "possesseur" de ton delegate.
    Maintenant, il y a quelques exceptions à  cette règle. Il me semble par exemple que UIWebView en fait partie, puisqu'elle retient son delegate.
    Une autre solution est de faire un "cancel" sur ta NSOperation associée quand tu détruit son delegate pour annuler l'opération. Et en profiter pourquoi pas pour mettre le delegate de la NSOperation à  nil (au cas où ta NSOperation continue un peu le temps de terminer un bout de code avant de traiter le isCancelled) pour eviter le BAD_ACCESS si tu détruis ton delegate trop tôt (par exemple un UIViewController qui est le delegate d'une NSOperation sauf qu'il a été "pop-é" ou "dismiss-é" entre temps)
  • colionelcolionel Membre
    14:58 modifié #3
    Merci pour ta réponse rapide !
    Je suis d'accord avec tout ce que tu as dis (un autre exemple d'exception est NSURLConnection qui retient son delegate).
    Et je vais faire attention à  gérer le cas ou il y a un opo ou un dismiss du delegate.

    Mais là  même sans action de l'utilisateur ca plante si je fais un assign :

    JSONWriterOperation *operation = [[JSONWriterOperation alloc] init];
    operation.delegate = self;
    [[GETaskManager sharedTaskManager].mainOperationQueue addOperation:operation];


    Si je debug je rentre immediatement dans la méthode main de mon operation, et dès le départ j'ai perdu la référence vers mon delegate.

    Tout rentre dans l'ordre si je retain mon delegate.

    Est ce que je dois en conclure qu'il faut toujours faire un retain du delegate dans le cas d'une NSOperation ?

    Est ce qu'il y a d'autres impact à  faire un retain sur mon delegate en multi-thread ? est ce qu'il y a des choses auxquels je dois faire attention (à  part faire un release de mon delegate dans le dealloc ?)

    Merci pour vos conseils en tout cas,
    Vincent.
  • AliGatorAliGator Membre, Modérateur
    14:58 modifié #4
    Il se peut que tu sois obligé de faire un retain de ton delegate dans le cas où tu doive gérer du multithreading et de l'asynchrone. Je te renvoie au "Multithreading Programming Guide" et au "Concourrency Programming Guide" pour ces points.

    Mais si tu fais un retain sur ton delegate, il faut effectivement faire attention en particulier au retain cycles (http://developer.apple.com/mac/library/documentation/Cocoa/Conceptual/MemoryMgmt/Articles/mmObjectOwnership.html)
Connectez-vous ou Inscrivez-vous pour répondre.