首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >内存管理

内存管理
EN

Stack Overflow用户
提问于 2011-05-15 13:07:14
回答 2查看 583关注 0票数 1

方法removeFromSuperView:是如何工作的?当我想要重新启动视图时,我遇到了内存访问错误的问题

代码语言:javascript
复制
- (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。结果非常奇怪。

代码语言:javascript
复制
//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

奇怪的是,为什么它在第一次按下时没有崩溃??

EN

回答 2

Stack Overflow用户

发布于 2011-05-15 13:13:43

从不使用RETAINCOUNT。很抱歉把它放在大写字母里,但我真的搞不懂为什么人们还在用它。这是一个错误的内存管理参考。请使用仪器或类似的工具。

票数 3
EN

Stack Overflow用户

发布于 2011-05-15 13:33:21

此时您不应该访问_mainView。这可能很难解释,所以请容忍我。我们将计数,但不是绝对的保留计数,只是你的代码对对象的声明。

您可以为对象分配内存,并使用_mainView指向该对象

代码语言:javascript
复制
_mainView = [[UIView alloc] initWithFrame:[[UIScreen mainScreen] bounds]];

您对该对象有1个所有权声明。当你将其添加为另一个视图的子视图时,该视图同样会声明所有权,但这不是你的,而是视图的。它让_mainView中的对象停留在那里的事实是一个意外,你不应该依赖它。然后释放对象:

代码语言:javascript
复制
[_mainView release];

您已放弃所有权声明--您现在有0个声明,您不应再尝试访问此对象。你不拥有它。同样,它仍然存在是因为另一个视图正在使用它,以及您仍然有指向它的指针,这都是偶然的*,您不应该依赖它们。

然后,当需要处理按钮按下时,您访问的是一个您没有所有权的对象:

代码语言:javascript
复制
[_mainView removeFromSuperView];

这会导致崩溃,这可能是意想不到的,但也不是不合理的。通过让你的所有权声明变为0,你告诉系统“我不再需要这个对象了。在这之后我不会再访问它了。如果它消失了,我不会受到影响。”但实际上,您确实需要它留在周围,并且您确实需要访问它。

那么,你应该做的就是移动这行:

代码语言:javascript
复制
[_mainView release];

添加到按钮操作内部,就在调用removeFromSuperview之后。

*第二个问题可以通过在释放后设置_mainView = nil;来避免,在这种情况下,但这不会解决更大的问题。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/6006603

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档