方法removeFromSuperView:是如何工作的?当我想要重新启动视图时,我遇到了内存访问错误的问题
- (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]);
}
每当有任何保留、分配或释放关键字时,我都会使用NSLog。结果非常奇怪。
//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
奇怪的是,为什么它在第一次按下时没有崩溃??
发布于 2011-05-15 05:13:43
从不使用RETAINCOUNT。很抱歉把它放在大写字母里,但我真的搞不懂为什么人们还在用它。这是一个错误的内存管理参考。请使用仪器或类似的工具。
发布于 2011-05-15 05:33:21
此时您不应该访问_mainView
。这可能很难解释,所以请容忍我。我们将计数,但不是绝对的保留计数,只是你的代码对对象的声明。
您可以为对象分配内存,并使用_mainView
指向该对象
_mainView = [[UIView alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
您对该对象有1个所有权声明。当你将其添加为另一个视图的子视图时,该视图同样会声明所有权,但这不是你的,而是视图的。它让_mainView
中的对象停留在那里的事实是一个意外,你不应该依赖它。然后释放对象:
[_mainView release];
您已放弃所有权声明--您现在有0个声明,您不应再尝试访问此对象。你不拥有它。同样,它仍然存在是因为另一个视图正在使用它,以及您仍然有指向它的指针,这都是偶然的*,您不应该依赖它们。
然后,当需要处理按钮按下时,您访问的是一个您没有所有权的对象:
[_mainView removeFromSuperView];
这会导致崩溃,这可能是意想不到的,但也不是不合理的。通过让你的所有权声明变为0,你告诉系统“我不再需要这个对象了。在这之后我不会再访问它了。如果它消失了,我不会受到影响。”但实际上,您确实需要它留在周围,并且您确实需要访问它。
那么,你应该做的就是移动这行:
[_mainView release];
添加到按钮操作内部,就在调用removeFromSuperview
之后。
*第二个问题可以通过在释放后设置_mainView = nil;
来避免,在这种情况下,但这不会解决更大的问题。
https://stackoverflow.com/questions/6006603
复制相似问题