iPhone dev – viewDidUnload子视图

我很难在UIViewController中找到一些方法,但首先我会说出我认为它们的意思(忽略界面构建器,因为我没有使用它):

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

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

>稍后会再次调用-loadView来重新创建视图吗?
>我在-viewDidLoad中创建了一些我没有制作ivar /属性的东西因为没有必要而且它将被视图保留(因为它们是它的子视图).因此,当视图发布时,它也会释放它们,对吧?视图发布后,它会释放所有子视图吗?因为我在-viewDidLoad中创建的所有对象都是[自我视图]的子视图.所以,如果他们已经被释放,为什么要在-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中它将被取消分配.所以最好总是使用属性来做这些事情,对吗?或不?

最佳答案

Will -loadView get called again to recreate the view later on?

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

When the view is released, will it release all its subviews?

是.

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

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

在这种情况下,当视图被取消分配时,标签将被释放.

你的例子中的内存管理很好.当你分配标签时,它的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…];

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

点赞