2009-05-29 8 views
1

Je suis en train de remplir un dictionnaire dynamique dans une boucle comme ceci:Peupler objet en Objective C

pseudo-code

myObject = new Object 
myDict = new Dictionary 
for(int i; i < 10;i++) 
    myObject.value1 = new data from somewhere 
    myObject.value2 = new data from somewhere 
    myDic = value:myObject key:i 
end for 

Ma question est en Objective-C, puis-je continuer à attribuer de nouvelles données au myObject sans le relâcher à chaque fois dans la boucle? J'essaie toujours de comprendre la gestion de la mémoire dans l'objectif-c.

+0

Que publieriez-vous pendant la boucle? Toutes les données (clés, valeurs et dictionnaire lui-même) sont toujours utilisées. –

Répondre

5

Cela dépend de ce que myObject est réellement et comment vous avez ses propriétés définies. En supposant que vous les avez définis pour libérer comme ici:

@property (nonatomic, retain) SomeClass *myProperty; 

alors oui, vous pouvez le faire. Les setters sont synthétisés automatiquement pour vous par la version objective-c et mis à zéro les anciennes valeurs des propriétés avant de conserver et d'assigner de nouvelles valeurs.

Cependant, bien qu'il n'y ait aucun problème avec votre gestion de la mémoire, il y a toujours un problème avec votre code. Rappelez-vous que myObject est un pointeur, tout comme en C ou C++. Cela signifie que si vous l'ajoutez à myDic, puis modifiez les propriétés de l'objet ultérieurement (par exemple lors de la prochaine itération de votre boucle for), ces modifications seront répercutées lorsque vous extrayez l'objet du dictionnaire à un moment donné dans le avenir. Ce que vous voulez est quelque chose comme ceci:

myObject = nil 
myDict = new Dictionary 
for(int i; i < 10;i++) 
    myObject = new Object 
    myObject.value1 = new data from somewhere 
    myObject.value2 = new data from somewhere 
    myDic setValue:myObject forKey:i 
    myObject release 
end for 

Qu'est-ce que cela ne fait libérer myObject après avoir mis dans le dictionnaire (toutes les classes de collecte de cacao conservent tous les objets que vous mettez en eux et libérer les objets quand ils sont enlevés ou la la collection elle-même est désallouée) donc vous n'avez pas de fuite, ainsi que d'allouer une nouvelle instance de Object à chaque itération afin de ne pas modifier le même objet encore et encore.

Si vous n'avez pas lu Apple Memory Management Guide for Cocoa, je recommande fortement de le faire. C'est très instructif.

0

La gestion de la mémoire dans Objective-C s'effectue par comptage de références. Lorsque vous allouez un objet, il a un nombre de références de 1. La méthode 'retain' augmente le nombre de références tandis que 'release' le diminue. Lorsque le nombre de références atteint 0, la méthode 'dealloc' est appelée (vous ne devez jamais appeler explicitement 'dealloc') et l'objet est libéré.

Vous pouvez également appeler 'autorelease' sur un objet, ce qui diminuera le nombre de références "quelque temps après". Cela vous permet de faire usage de l'objet sans vous soucier de le libérer.

Pour votre question. Lorsque vous ajoutez un objet à un conteneur, un appel "retain" est effectué sur l'objet inséré. Cela signifie que vous devez « libérer » l'objet inséré:

NSMutableDictionary *myDict = [[NSMutableDictionary alloc] init]; 
for(int i = 0; i < 10; ++i) { 
    Object *myObject = [[Object alloc] init]; 
    [myDict setObject:myObject forKey:[NSNumber numberWithInt:i]]; 
    [myObject release]; 
} 

Vous pouvez également utiliser:

Object *myObject = [[[Object alloc] init] autorelease]; 

et vous ne serait pas appeler « libération » après l'insertion.

0

Votre question est très ouverte, cela dépend de la façon dont votre Object et Dictionary est implémentée.D'abord, vous allouez l'objet une seule fois et le relâchez en boucle 10 fois -> problème de mémoire.

Si nous dépassons cela. Supposons que vous allouer un nouvel objet à chaque itération de la boucle. Prenez NSMutableDictionary et MyObject qui étend NSObject en tant qu'exemples de votre objet et du dictionnaire.

Lorsque vous appelez setObject: forKey sur l'instance NSMutableDictionary, l'objet reçoit l'appel retain afin que le dictionnaire en garde la référence.

Lorsque vous le release à la fin de l'itération le dictionnaire garde toujours la référence à lui donc c'est ok.

Une autre chose à garder à l'esprit si vous utilisez ce dans une grande boucle:

Object *myObject = [[[Object alloc] init] autorelease]; 

est le fait que les objets vont à autoreleased AutoRelease piscine. Le pool est nettoyé à la fin du traitement de l'événement en cours. Si vous créez beaucoup d'objets, cela peut prendre beaucoup de temps à la fin du traitement de l'événement. Dans ce cas, vous pourriez choisir de créer votre propre pool autorelease uniquement pour la boucle - mais je suppose que c'est un sujet plus avancé.

Jetez un coup d'œil à certaines références de gestion de mémoire Objective-c et Apple.

0

Ce que vous faites fonctionne avec un seul objet et place cet objet dans le dictionnaire dix fois. Il ne met pas dix objets distincts dans le dictionnaire.