开发者

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

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜