2011-07-06 3 views
0

J'ai lu presque toutes les questions ici sur la gestion de la mémoire qui implique NSStrings, mais je ne peux pas vraiment résoudre ce problème.Fuite de mémoire avec NSString

@interface:

@property (nonatomic, retain) NSString *criticalTranscription; 

@implementation: viewDidLoad:

criticalTranscription = [[NSString alloc] init]; 

NSArray *paragraphs = [doc valueForKeyPath:@"critical.text"]; 
for(int i = 0; i < [paragraphs count]; i++) 
{ 
    criticalTranscription = [criticalTranscription stringByAppendingString:[[paragraphs objectAtIndex:i] valueForKey:@"p"]]; 
    criticalTranscription = [criticalTranscription stringByAppendingString:@"\n\n"]; 
} 
[transcription setText:criticalTranscription]; 

@XIB A UISegmentedControl avec un IBAction lié à:

- (IBAction) changeText:(id)sender 
{ 
    if(transcriptionSelector.selectedSegmentIndex == 1) 
    [transcription setText:diplomaticTranscription]; 
    else 
    [transcription setText:criticalTranscription]; 
} 

Lorsque je change la valeur de l'UISegmentControl (première chose juste après chargement, rien d'autre court), je lance dans cette erreur (NSZombieEnabled = OUI):

2011-07-07 01:10:43.639 Transcribe[404:707] *** -[CFString length]: message sent to deallocated instance 0x1189300 

Je ne vois rien pertinent dans le backtrace. Sans NSZombieEnabled criticalTranscription pointe juste vers des tableaux aléatoires ou autre chose. Il n'y a pas d'autre utilisation de la variable ou des versions.

J'ai couru analyser sans fuites suspectes.

Quel est le problème?

+0

Où créez-vous et définissez 'diplomaticTranscription'? – PengOne

Répondre

3

Le problème est que vous écrasez une référence à une chaîne que vous possédez avec une chaîne qui ne vous appartient pas. Toutefois, n'utilisez pas cette approche, car elle pollue le pool autorelease avec des chaînes inutiles. Au lieu de cela, utilisez une chaîne mutable et ajoutez des chaînes à l'instance de chaîne mutable unique. Pour utiliser la gestion de la mémoire intégrée de la propriété, vous devez utiliser self.criticalTranscription et pas seulement criticalTranscription. Sans le self., vous utilisez directement la variable d'instance.

+0

Doh! Vous cherchez une heure déjà! Merci! – Patrick

1

Dans votre boucle

criticalTranscription = [criticalTranscription stringByAppendingString:[[paragraphs objectAtIndex:i] valueForKey:@"p"]]; 
criticalTranscription = [criticalTranscription stringByAppendingString:@"\n\n"]; 

vous définissez criticalTranscription à un objet chaîne autoreleased mais pas retenir, ainsi la mort flamboyante.

Vous pouvez le conserver ou utiliser une propriété avec @property(nonatomic, copy)NSString *criticalTranscription; et utiliser la propriété plutôt que l'ivar.

1

Deux problèmes:

  • Vous fuit la première instance de la chaîne
  • Chaque valeur suivante vous attribuez à il devient autoreleased

Pour résoudre ce problème, la meilleure façon est pour modifier criticalTranscription à un NSMutableString.Ensuite, vous pouvez faire:

criticalTranscription = [[NSMutableString alloc] init]; 

NSArray *paragraphs = [doc valueForKeyPath:@"critical.text"]; 
for(int i = 0; i < [paragraphs count]; i++) 
{ 
    [criticalTranscription appendString:[[paragraphs objectAtIndex:i] valueForKey:@"p"]]; 
    [criticalTranscription appendString:@"\n\n"]; 
} 
[transcription setText:criticalTranscription]; 

... Sinon,

[criticalTranscription appendFormat:@"%@\n\n", [[paragraphs objectAtIndex:i] valueForKey:@"p"]]; 

Notez également que vous devez appeler release sur criticalTranscription une fois que vous avez terminé avec elle, que ce soit à la fin de votre -viewDidLoad ou dans son correspondant -viewDidUnload.