How is method removeFromSuperView: really works?
I got a problem of memory bad access when I want to reinit the view
- (id)init {
if (!(self = [super init]))
return nil;
_mainView = [[UIView alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
NSLog(@"retainCount :%d", [_mainView retainCount]);
UIButton *reInitButton = [[UIButton alloc] initWithFrame:CGRectMake(0.0f,0.0f,90.0f,35.0f)];
[reInitButton addTarget:self action:@selector(buttonDidTapped:) forControlEvents:UIControlEventTouchUpInside];
[[self view] addSubView:_mainView];
NSLog(@"retainCount :%d", [_mainView retainCount]);
[_mainView release];
NSLog(@"retainCount :%d", [_mainView retainCount]);
return self;
}
- (void)buttonDidTapped:(id)sender {
[_mainView removeFromSuperView]; //crash during second times press the button
NSLog(@"retainCount :%d", [_mainView retainCount]);
_mainView = [[UIView alloc] initWithFrame[[UIScreen mainScreen] bounds]];
[[self view] addSubView:_mainView];
NSLog(@"retainCount :%d", [_mainView retainCount]);
[_mainView release];
NSLog(@"retainCount :%d", [_mainView retainCount]);
}
I have NSLog every times there are any retain or alloc or release keyword. And the result is very weird.
//init
retainCount : 1
retainCount : 2
retainCount : 1
//1st time pressed button
retainCount : 1 //remove super view didn't decrease
retainCount : 2
retainCount : 1
//2nd time pressed button
retainCount : 0 //crash. Memory bad access
The weird thing is why it didn’t crash on 1st time pressed??
I think your problem is here:
You’ve dropped your reference to
_mainView, and yet, by my reading, that’s a member variable that you’ll keep around and continue to invoke methods on. That’s not valid. Once you’ve called-release, you’ve essentially told the system you’re not going to use that object again, and you can’t do anything useful with a stale pointer to that object, like you do when you call-removeFromSuperViewon it later.If you want to continue to keep
_mainViewaround and call code on it, you need to keep a reference. Perhaps you should move the release to your object’s-deallocmethod. Alternatively you could-releaseit in the button method and re-create a new view the next time you need to.As a helpful tip, a lot of programmers like to reset objects to
NULL(ornilin objC-speak) after releasing them, as a reminder that you can’t use that object again. If you-releasesomething, you’d better mean it.Lastly, I suggest you Google the term “reference counting” and read up on it; it’s a more generic idiom than the specifics of
NSObject, and it is likely to be useful to think of the basics and how you might implement this in another language, like say, C. This will help you reason better about reference counted objects.