2011-07-06 185 views
0

我几乎读到关于涉及NSStrings的内存管理的所有问题,但我不能真正解决这个问题。内存泄漏与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 一个UISegmentedControl与IBAction为连接至:

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

当我改变值UISegmentControl(之后的第一件事)装载,没有别的运行),我遇到这个错误(NSZombieEnabled = YES):

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

我无法看到回溯任何相关信息。没有NSZombieEnabled criticalTranscription只是指向随机数组或其他东西。变量或任何版本没有进一步的用法。

我跑分析没有任何可疑的泄漏。

有什么问题?

+0

你在哪里创建并设置'diplomaticTranscription'? – PengOne

回答

3

问题是,您正在覆盖您拥有的字符串的引用,而您不拥有该字符串。

// you own the empty string returned here 
criticalTranscription = [[NSString alloc] init]; 

NSArray *paragraphs = [doc valueForKeyPath:@"critical.text"]; 
for(int i = 0; i < [paragraphs count]; i++) 
{ 
    // immediately overwrite allocated instance (that you own) 
    criticalTranscription = [criticalTranscription stringByAppendingString:[[paragraphs objectAtIndex:i] valueForKey:@"p"]]; 
    criticalTranscription = [criticalTranscription stringByAppendingString:@"\n\n"]; 
} 

但是,不要使用这种方法,因为它会使用不必要的字符串污染autorelease池。相反,使用可变字符串并将字符串附加到单个可变字符串实例。

此外,为了利用该物业的内置内存管理,您需要使用self.criticalTranscription而不仅仅是criticalTranscription。如果没有self.,则直接使用实例变量。

+0

Doh!已经找了一个小时了!谢谢! – Patrick

1

在你的for循环

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

要设置criticalTranscription到自动释放字符串对象,但不保留它,因此燃烧死亡。

您可以保留它或使用属性@property(nonatomic, copy)NSString *criticalTranscription;并使用属性而不是伊娃。

1

两个问题:

  • 你泄露字符串
  • 分配给它的每一个后续值的第一个实例是越来越自动释放

为了解决这个问题,最简单的方法是将criticalTranscription更改为NSMutableString。然后,你可以这样做:

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]; 

...或者,

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

另外请注意,您需要调用criticalTranscriptionrelease一旦你用它做,无论是在你的-viewDidLoad或结束其相应的-viewDidUnload