Memory Leak - Instruments, Objective-C
I have a UITextField and in the delegate class I have a UITableView. Here is the code:
- (BOOL) textField: (UITextField *)theTextField shouldChangeCharactersInRange: (NSRange)range replacementString: (NSString *)stri开发者_如何学Pythonng {
value = [[theTextField.text stringByReplacingCharactersInRange:range withString:string] retain];
[valueTable reloadData];
return YES;
}
"value" is an NSString declared at the top of my class as "NSString *value;" and "valueTable" is just a UITableView. When I test for memory leaks, I am getting a "100%" memory leak on the line "value = [[theTextField.text stringByReplacing..." and I tried removing the "retain" on that line. However then later on when I called upon "value," it was nil, which is not good.
So how can I fix the memory leak? And what is the memory leak? Thanks!
The memory that is being leaked is the memory pointed to by value
.
Every time your text field changes, the method stringByReplacingCharactersInRange...
is returning an autoreleased NSString object. You are correct to retain it, so that it isn't deallocated. The problem, is that you now own memory somewhere. (You own that NSString by retaining it.)
The next time that method is called, when the user changes the text in that field, you're pointing value
to a completely different memory location. The original memory that you had retained still exists, and will continue to persist forever. (Since you never released it.)
It's very important to match any retain
method calls with an associated release
. You could do either:
...
if (value) {
[value release];
}
value = ...;
...
OR
You can define the NSString *value
as a property on your class, like:
@property (nonatomic, retain) NSString *value);
/* Implementation file */
@synthesize value;
Then simply use:
...
self.value = ...;
...
Also, since you're always going to have retained memory after that method has been called, you'll need to release value
when your class is deallocated, as was mentioned in another answer:
- (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];
}
Edit: It sounds like you should definitely read Apple's memory management guide before continuing: http://developer.apple.com/library/mac/#documentation/cocoa/conceptual/MemoryMgmt/MemoryMgmt.html
You should release value
later on when you're done with it. For example, you can release it when in the delegate's dealloc
method:
- (void)dealloc {
[value release];
// other memory management code...
[super dealloc];
}
see Apple's documentation on memory management.
As the others have mentioned, the problem is in the following line:
value = [[theTextField.text
stringByReplacingCharactersInRange:range withString:string] retain];
The issue with this code is that you are not releasing the old value of value
before assigning the new value. Changing the code to the following should fix the leak, provided there are no other unforeseen problems elsewhere:
- (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];
}
精彩评论