【问题标题】:iPhone dev - viewDidUnload subviewsiPhone 开发 - viewDidUnload 子视图
【发布时间】:2010-06-02 15:05:05
【问题描述】:

我很难理解 UIViewController 中的几个方法,但首先我会说一下我认为它们的用途(忽略界面构建器,因为我没有使用它):

-init:初始化非视图相关的东西,在内存不足的情况下不需要释放(即不是对象或无法轻松重新创建的对象)。
-loadView:创建视图设置[self view]属性。
-viewDidLoad:创建所有其他视图元素
-viewDidUnload:释放在-viewDidLoad中创建的对象。
didReceiveMemoryWarning:内存不足的情况,释放不必要的东西例如缓存的数据,如果这个视图没有超级视图,那么[super didReceiveMemoryWarning] 将继续释放(卸载)视图并调用-viewDidUnload
-dealloc:释放所有内容
-viewWillAppear:-viewDidAppear:-viewWillDisappear:-viewDidDisappear: 不言自明,除非您想对这些事件做出回应(做某事),否则没有必要。

我不确定有几件事。首先,Apple 文档说当调用-viewDidUnload 时,视图已经被释放并设置为nil。

  1. 以后会再次调用-loadView 重新创建视图吗?
  2. 我在-viewDidLoad 中创建了一些我没有为其创建ivar/属性的东西,因为没有必要,它会被视图保留(因为它们是它的子视图)。所以当视图被释放时,它也会释放那些,对吧?当视图被释放时,它会释放它所有的子视图吗?因为我在-viewDidLoad 中创建的所有对象都是[self view] 的子视图。因此,如果它们已经发布,为什么还要在 -viewDidUnload 中发布它们?我可以理解在这些方法中加载和卸载视图可见时所需的数据,但就像我问的那样,如果子视图已经被释放,为什么还要释放它们?

编辑:阅读其他问题后,我想我可能已经明白了(我的第二个问题)。在我只使用局部变量的情况下,分配它,使其成为子视图并释放,它的保留计数为 1(从将其添加为子视图),因此当视图被释放时也是如此。现在对于带有指向它们的 ivars 的视图元素,我没有使用属性,因为没有外部类需要访问它们。但现在我认为那是错误的,因为在这种情况下:

// MyViewController.h
@interface MyViewController : UIViewController {
    UILabel *myLabel;
}

// MyViewController.m
. . .
- (void)viewDidLoad {
    myLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 40, 10)];
    [myLabel setText:@"Foobar"];
    [[self view] addSubview:myLabel];
}

- (void)viewDidUnload [
    // equivalent of [self setMyLabel:nil]; without properties
    [myLabel release];
    myLabel = nil;
}

在这种情况下,标签将在释放后发送-release 消息,因为 ivar 没有保留它(因为它不是属性)。但是对于一个属性,保留计数将是两个:保留它的视图和属性。那么在-viewDidUnload 中,它将被释放。所以最好总是为这些东西使用属性,对吗?或不?

【问题讨论】:

    标签: iphone objective-c memory-management uiviewcontroller


    【解决方案1】:

    以后会再次调用-loadView 重新创建视图吗?

    是的,只要有人访问 view 属性。

    当视图被释放时,它会释放它所有的子视图吗?

    是的。

    对于以后不需要的标签之类的东西,通常的做法是在将它们附加到视图后简单地释放它们:

    UILabel *foo = [[UILabel alloc] init…];
    [self.view addSubview:foo];
    [foo release];
    

    在这种情况下,标签将在视图被释放时被释放。


    您的示例中的内存管理很好。当您 alloc 标签时,其 retainCount 跳到 1,视图保留它(retainCount = 2),然后视图被释放并释放标签(rc = 1),然后您最终释放给自己贴上标签(rc = 0,dealloc)。

    为了让事情更清楚——变量myLabel 没有明确保留标签,但你仍然拥有它,因为你分配了它。这是 Cocoa 内存管理的基本规则之一:alloc+1、retain+1、release-1、autorelease-1 之后。

    例子:

    @property(retain) UILabel *foo;
    self.foo = [[UILabel alloc] init…];
    

    这将是一个泄漏,因为标签在分配期间获得 +1,而在为 foo 属性生成的 setter 中获得另一个 +1。阅读 Cocoa 内存管理指南或Scott Stevenson’s Objective-C tutorial。 Cocoa 中的内存管理非常简单,经过一番思考,您应该在所有情况下都非常舒适。

    【讨论】:

    • 谢谢,我现在明白了。但是我对使用属性(我编辑的帖子的最后一部分)是否正确?
    • 我的要求只是为了确认这一点:除了卸载您将在-viewDidLoad 中重新创建的数据之外,-viewDidUnload 用于释放仍保留 @ 子视图的属性 ([self setProperty:nil]) 987654340@,[self view] 已经释放,因此可以释放它们。我说的对吗?
    • 但是我以为例子里面有代码不起作用?因为成员变量 myLabel 永远不会保留 UILabel(只有视图会保留),但它仍然在 -viewDidUnload 中释放它。或者你是在谈论我之后描述的内容?我要决定的是我是否应该总是将属性用于这样的事情(我需要一个成员变量)?
    • 谢谢,我现在明白了。我忘记了 alloc 增加了保留计数。所以如果我不需要暴露成员变量,如果我不想使用属性,我也不需要。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-20
    • 1970-01-01
    • 2010-11-15
    相关资源
    最近更新 更多