首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >以编程方式向视图添加子视图:应该在哪里管理内存?

以编程方式向视图添加子视图:应该在哪里管理内存?
EN

Stack Overflow用户
提问于 2011-08-23 23:13:56
回答 4查看 388关注 0票数 0

我读过编号/doc/uid/TP40007457-CH101-SW19,但我仍然不太清楚它是如何工作的。

代码语言:javascript
复制
@property (nonatomic, retain) UIButton *startButton;
@property (nonatomic, retain) UITextView *infoTextView;

这是一个显示在制表栏中的视图控制器。

代码语言:javascript
复制
- (void)loadView
{
    UIView *newView = [[UIView alloc] init];

    //self.startButton and addSubivew retains the button obect; retain count = 2
    UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
    //autorelases
    self.startButton = button;
    [newView addSubview:startButton];    

    //addSubview retains infoTextView; self.infoTextview retains; retain count: 2
    self.infoTextView = [[[UITextView alloc] initWithFrame:CGRectMake(0.0, 0.0, 280.0, 270.0)] autorelease];
   //autoreleased
    [newView addSubview:infoTextView];

    //View controller retains the view hierarchy
    self.view = newView;
    [newView release];

}


//customization of the button and textview (text, frame, center, target-action etc)
- (void)viewDidLoad
{
    [super viewDidLoad];
    [self loadStartButton];
    [self loadTextView];

}

//because these have retain properties, they are released through nil
- (void)viewDidUnload
{
    self.startButton = nil;
    self.infoTextView = nil; //retain counts - 1
    [super viewDidUnload];
    // Release any retained subviews of the main view.
    // e.g. self.myOutlet = nil;
}

- (void)dealloc
{
    [startButton release];
    [infoTextView release]; //retain counts -1
    [super dealloc];
}

我的问题是: UIView对象是否应该保留2的计数?我认为视图控制器保留了UIView对象,viewController.view也保留了UIView对象(通过添加子视图)。这是正确的方式来看待它的概念吗?因为我的viewController也在管理它的.view属性所拥有的对象。

但是,我不确定在内存不足的情况下是否同时调用了viewDidUnload和dealloc。我是正确地释放了它们还是设置了内存泄漏?

(任何关于将代码放在错误位置的评论也会有所帮助)

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2011-08-23 23:50:22

在内存不足的情况下,我不认为您的视图控制器会被取消。你的观点会。viewDidUnload将被调用,而不是dealloc。没关系。你的按钮会被释放。视图控制器的引用将由viewDidUnload代码释放,来自addSubview的引用将由视图的默认dealloc代码(或默认代码中的某个地方)释放。

当您确实释放您的视图控制器,如果有,两者都将被调用。dealloc中的发布语句将什么也不做,因为它们将等同于零发布,这是一个无操作。没关系。

不过,我认为您可以从dealloc中删除这些发布语句,因为在不首先调用viewDidUnload的情况下,dealloc永远不会被调用。

票数 0
EN

Stack Overflow用户

发布于 2011-08-23 23:49:52

从概念上讲,我并不太担心实际的保留数。我试着更多地平衡我的电话。如果在方法中本地保留,那么我将(很可能)需要在同一方法中调用一个版本。

代码语言:javascript
复制
...
    UIView *newView = [[UIView alloc] init]; <---- retain count gets +1
    // ... do more stuff
    [newView release]; newView = nil;        <---- retain count gets -1
...

在上面的呼吁是平衡的,所以我们是好的。

代码语言:javascript
复制
/*
 * This creates an autoreleased button. Therefore I am not taking a retain on 
 * it so I don't need to release it
 */
UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect]; 

//autorelases <---- this comment is redundant as the code states this

它对ivars的工作方式略有不同,因为通常您试图平衡initdealloc方法中的调用,然后在整个类中使用属性来做正确的事情。

代码语言:javascript
复制
/*
 * As we have used sythesized properties the memory management is taken care 
 * for us if we use dot notation or call the setters/getters
 */
self.startButton = button;
  OR
[self setStartButton:button];


/*
 * Because this is an ivar and not a local method variable we balance our calls
 * in the `init` (if we need to, remember ivars are initialized to nil for us)
 * and `dealloc` methods.
 */
- (id)initWithButton:(UIButton *)startButton
{
    self = [super init];
    if (self) {
        /*
         * Notice we don't use self. You should try to access ivar 
         * directly in your init and dealloc methods to avoid side effects
         */
        _startButton = [startButton retain];
    }
    return self;
}

- (void)dealloc
{
   // Release any other ivars

   /*
    * Notice we don't use self. You should try to access ivar 
    * directly in your init and dealloc methods to avoid side effects
    */
   [_startButton release];
   [super dealloc];
}

// NOTE
// I have prefixed my ivars to make it more explicit when I am accessing them 
// directly as opposed to accessing them through dot notation of normal method
// calls

添加视图通常不是我们关心的问题,因为我们相信框架将正确地管理其任务内存。

代码语言:javascript
复制
/*
 * We don't need to worry about this taking a +1 as our code is doing our
 * management correctly
 */
[newView addSubview:startButton]; 

内存管理摘要

  • 局部方法变量-通常情况下,保留/释放调用应该在该方法中得到平衡。
  • -通常情况下,保留/释放调用应该与init中的retaindealloc中的release进行平衡,然后始终在整个类中使用属性来管理所有其他内存任务。
  • 不要依赖于检查对象的保留计数,只需平衡内存管理调用

viewDidUnload

一般来说,您可以看到viewDidLoadviewDidUnload是一对匹配的。在viewDidLoad中创建的任何东西都可以在viewDidUnload中释放。您不应该在viewDidUnload中发布任何无法轻松重新创建的内容,检查文档中的UIViewController

您的视图只有在当前不可见的屏幕和内存级别较低的情况下才会卸载。

票数 0
EN

Stack Overflow用户

发布于 2011-08-23 23:51:38

看起来,您的UIView对象将保留两个计数。但这不一定是坏事。由于内存不足,视图可能会来来去去,而且如果您不希望每次加载视图时都重新创建UI元素,那么拥有视图控制器是一件合理的事情。

通常,低内存条件将导致您的视图被卸载,因此将调用viewDidUnload。在大多数情况下不会调用视图控制器的dealloc方法,除非对视图控制器的所有引用都以某种方式被删除。

通常情况下,我的viewDidUnload基本上是“撤消”viewDidLoad所发生的任何事情。当出现低内存情况时,视图将被卸载,在加载时完成的工作将被取消。当视图被重新加载时,它基本上会被重做。你在这里做的似乎不止这些。您的viewDidUnload正在取消在loadView中所做的工作。在本例中,我认为您还可以:当视图重新加载时,它应该(我认为)调用两个loadView。不过,作为一般规则,我喜欢匹配viewDidLoad和viewDidUnload。它使事情与不直接实现loadView的视图控制器更加一致。

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

https://stackoverflow.com/questions/7168640

复制
相关文章

相似问题

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