我在这里几乎阅读了关于涉及NSStrings的内存管理的所有问题,但我无法真正解决这个问题。
@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 带有IBAction的UISegmentedControl链接到:
- (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 :(得分: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"];
}
但是,请勿使用此方法,因为它会使用不必要的字符串污染自动释放池。相反,使用可变字符串并将字符串附加到单个可变字符串实例。
此外,为了利用该属性的内置内存管理,您需要使用self.criticalTranscription
而不仅仅是criticalTranscription
。如果没有self.
,则直接使用实例变量。
答案 1 :(得分:1)
在你的for循环中
criticalTranscription = [criticalTranscription stringByAppendingString:[[paragraphs objectAtIndex:i] valueForKey:@"p"]];
criticalTranscription = [criticalTranscription stringByAppendingString:@"\n\n"];
您正在将criticalTranscription
设置为自动释放的字符串对象但不保留它,从而导致火焰死亡。
您可以保留它或使用@property(nonatomic, copy)NSString *criticalTranscription;
的属性并使用该属性而不是ivar。
答案 2 :(得分: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"]];
另请注意,您需要在release
完成criticalTranscription
之后,-viewDidLoad
或其相应的-viewDidUnload
。