2011-07-06 98 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