2009-10-01 10 views
1

Ceci est une question de suivi d'une question précédente, qui, espérons-le, est un peu plus claire. Je suis juste curieux de voir comment fonctionne le code présenté ci-dessous, en particulier la variable myString qui sortira. Cela ne semble pas provenir de la sortie?Conserver le compte et copier dans Setter?

CODE

// IMPLEMENT 
@implementation CelestialBody 
- (void)setName:(NSString *)newName{ 
    if(name != newName) { 
     [name release]; 
     name = [newName copy]; 
    } 
} 
- (void)dealloc{ 
    [name release]; 
    name = nil; 
    [super dealloc]; 
} 
@end 

.

// ------------------------------------------------------------------- ** 
// MAIN: 30th September 2009 
// ------------------------------------------------------------------- ** 

#import <Foundation/Foundation.h> 
#import "CelestialBody.h" 

int main (int argc, const char * argv[]) { 
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; 

    CelestialBody *newPlanet = [[CelestialBody alloc] init]; 
    NSString *myString = [[NSString alloc]initWithFormat:@"go home"]; 
    NSLog(@"RetainCount_1: %d",[myString retainCount]); 

    [newPlanet setName: myString]; 
    NSLog(@"RetainCount_2: Incremented by copy in setName");  

    // Clean up 
    NSLog(@"RetainCount_2: %d -Before Release",[myString retainCount]); 
    [newPlanet release]; 
    [myString release]; 
    [pool drain]; 
    NSLog(@"RetainCount_1: %d -After Release",[myString retainCount]); 
    return 0; 
} 
// ------------------------------------------------------------------- ** 

SORTIE

Running… 
2009-10-01 09:28:50.395 RetainCount_1: 1 
2009-10-01 09:28:50.399 RetainCount_2: Incremented by copy in setName 
2009-10-01 09:28:50.399 RetainCount_2: 2 -Before Release 
2009-10-01 09:28:50.400 RetainCount_1: 1 -After Release 
Debugger stopped. 

Je relis actuellement le Guide de gestion Memeory pour essayer de voir ce que je l'ai manqué.

merci beaucoup

EDIT

ajouté un la sortie du dealloc, il semble que c'était ce que je manque.

- (void)dealloc{ 
    [name release]; 
    name = nil; 
    [super dealloc]; 
} 

gary

+2

Ne vous inquiétez pas pour -retainCount. Ne l'appelle pas. Ne l'imprime pas. Ne le considère pas. Ce n'est pas utile. Les comptes retenus doivent être considérés comme des deltas; vous augmentez et décrémentez, mais la valeur sous-jacente n'est pas votre préoccupation. – bbum

Répondre

3

est la myString variables être libérés.

[myString release]; 

Tous les signes indiquent oui.

Cela ne semble pas provenir de la sortie?

NSLog(@"RetainCount_2: %d",[myString retainCount]); 
[myString release]; 

sortie de votre déclaration NSLog ne reflète pas le message release parce que le message release n'a pas encore eu lieu.

De même, ne vous inquiétez pas du nombre de retenues. Ils peuvent être très trompeurs. Tant que vous suivez les règles de Cocoa et ne créez aucun cycle de propriété (A possède B possède C possède A), vous aurez rarement un problème.

+0

Désolé mon erreur, j'ai mis à jour le code. – fuzzygoat

+3

+1. Ne vous inquiétez pas de conserver les comptes. OMI, Apple devrait supprimer complètement la méthode retainCount. Il est trop tentant pour les débutants de penser qu'ils peuvent compter dessus plutôt que d'apprendre les règles. – Chuck

+2

N'a pas d'accord plus sur ne pas s'inquiéter des comptes retenus spécifiques. Par exemple, si vous avez fait 'myString' un' NSMutableString', le nombre de retain sera toujours 1 après 'setName:'. Pourquoi? Parce que 'copy' crée un tout nouvel objet lors de la copie d'objets mutables. Il 'conserve des objets immuables, car il est inutile de copier des choses dont les valeurs ne peuvent pas changer. Peu importe le nombre de retenues; il suffit de suivre les règles et vous serez toujours bien. – Alex

1

Je suppose que [copie newName] ne copie pas en fait le NSString, parce que NSString est immuable? Je n'ai jamais pensé à ça, mais ça a du sens pour moi.

À la fin de votre programme, vous lancez newPlanet et myString. Ma question est, libérez-vous le nom de la variable d'instance dans la méthode -dealloc de CelestialBody? Si vous ne l'êtes pas, je crois que vous fuyez la mémoire là-bas.

  1. Créer myString: le retainCount de NSString est 1
  2. [newPlanet setName:]: le retainCount de NSString est 2
  3. [newPlanet release]: Le retainCount du NSString est 2? Je suppose que vous ne le publiez pas dans -dealloc.
  4. [Communiqué myString]: le retainCount de NSString est 1
+4

"Je suppose que [la copie de newName] ne copie pas réellement NSString, parce que NSString est immuable?" Corrigez, mais ne vous inquiétez pas à ce sujet, ou gardez des comptes. Conserver les comptes peut être très trompeur, en partie à cause d'optimisations comme celle-ci. Tant que vous suivez les règles de gestion des objets de Cocoa, il est peu probable que vous ayez un problème. –

2

Ceci n'est pas une réponse à votre question, mais une explication de ce que vous voyez: Le dernier appel à retainCount est envoyé à un objet désalloué, qui est un comportement indéfini. L'objet n'arrive pas encore à être écrasé, donc il continue de fonctionner "normalement" dans le sens où la méthode dispatch peut toujours voir les anciennes données qui s'y trouvent et ne réalise pas qu'elles ne sont pas valides. Vous ne recevrez jamais 0 d'appeler retainCount, car un tel objet ne peut pas exister.

Questions connexes