我有一个UITextField,在委托类中我有一个UITableView。这是代码:
- (BOOL) textField: (UITextField *)theTextField shouldChangeCharactersInRange: (NSRange)range replacementString: (NSString *)string {
value = [[theTextField.text stringByReplacingCharactersInRange:range withString:string] retain];
[valueTable reloadData];
return YES;
}
“value”是在我的类顶部声明为“NSString * value;”的NSString而“valueTable”只是一个UITableView。当我测试内存泄漏时,我在“value = [[theTextField.text stringByReplacing ...”这一行上得到“100%”内存泄漏,我尝试删除该行上的“retain”。然而,后来当我呼吁“价值”时,它是零,这是不好的。
那么如何修复内存泄漏?什么是内存泄漏?谢谢!
答案 0 :(得分:1)
正在泄露的内存是value
指向的内存。
每次文本字段更改时,方法stringByReplacingCharactersInRange...
都会返回自动释放的NSString对象。保留它是正确的,因此不会取消分配。问题是,你现在在某个地方拥有记忆。 (你通过保留NSString来拥有它。)
下次调用该方法时,当用户更改该字段中的文本时,您将value
指向完全不同的内存位置。您保留的原始内存仍然存在,并将继续持续存在。 (因为你从未发布它。)
非常重要可以将任何retain
方法调用与关联的release
进行匹配。你可以这样做:
...
if (value) {
[value release];
}
value = ...;
...
或强>
您可以将NSString *value
定义为您班级的属性,例如:
@property (nonatomic, retain) NSString *value);
/* Implementation file */
@synthesize value;
然后简单地使用:
...
self.value = ...;
...
此外,由于在调用该方法后您总是会保留内存,因此当您的类被释放时,您需要释放value
,如另一个答案所述:
- (void)dealloc {
// Only do *one* of the two following releases
// (1) If you're not using properties:
[value release];
// (2) If you are using properties:
self.value = nil;
[super dealloc];
}
编辑:听起来你应该继续阅读Apple的内存管理指南: http://developer.apple.com/library/mac/#documentation/cocoa/conceptual/MemoryMgmt/MemoryMgmt.html
答案 1 :(得分:0)
稍后您应该在完成后释放value
。例如,您可以在委托的dealloc
方法中释放它:
- (void)dealloc {
[value release];
// other memory management code...
[super dealloc];
}
请参阅Apple关于内存管理的文档。
答案 2 :(得分:0)
正如其他人所说,问题出在以下几行:
value = [[theTextField.text
stringByReplacingCharactersInRange:range withString:string] retain];
此代码的问题在于,在分配新值之前,您未发布value
的旧值。将代码更改为以下内容应该可以解决泄漏问题,前提是其他地方没有其他无法预料的问题:
- (BOOL)textField:(UITextField *)theTextField
shouldChangeCharactersInRange:(NSRange)range
replacementString:(NSString *)string {
NSString *newValue = [[theTextField.text
stringByReplacingCharactersInRange:range withString:string] retain];
[value release];
value = newValue;
[valueTable reloadData];
return YES;
}
- (void)dealloc {
[value release];
[super dealloc];
}