iPhone开发 - viewDidUnload子视图

4
我很难理解UIViewController中的一些方法,但首先我会说一下我认为它们的用途(忽略界面构建器,因为我不使用它):
- init:初始化非视图相关的东西,在低内存情况下不需要释放(即不是对象或难以重新创建的对象)。 - loadView:创建视图并设置[self view]属性。 - viewDidLoad:创建所有其他视图元素。 - viewDidUnload:释放在-viewDidLoad中创建的对象。 - didReceiveMemoryWarning:低内存情况下,释放不必要的东西,如缓存数据,如果此视图没有superview,则[super didReceiveMemoryWarning]将继续释放(卸载)视图并调用-viewDidUnload。 - dealloc:释放所有内容。 - viewWillAppear:, viewDidAppear:, viewWillDisappear:, viewDidDisappear:自我说明,除非您想对这些事件做出响应(执行某些操作),否则不必要。
我有几件事不确定。首先,苹果文档说当-viewDidUnload被调用时,视图已经被释放并设置为nil。
- loadView是否会在以后重新创建视图? - 我在-viewDidLoad中创建了一些东西,因为没有必要并且它将被视图保留(因为它们是其子视图)。所以当视图被释放时,它也会释放它们,对吗?当视图被释放时,它会释放所有子视图吗?因为我在-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;
}

在这种情况下,由于ivar没有对其进行保留(因为它不是一个属性),因此在释放之后,标签将收到“-release”消息。但是,使用属性时保留计数将为两个:视图保留和属性保留。因此,在“-viewDidUnload”中它将被释放。所以最好总是使用属性处理这些事情,我说的对吗?还是不对?
1个回答

2

-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的Objective-C教程。Cocoa中的内存管理非常简单,经过一点思考后,您应该可以在所有情况下都完全自如。


谢谢,我现在明白了。但是,我最后编辑的帖子中使用属性的部分是正确的吗? - mk12
我所询问的只是确认一下:除了在 -viewDidLoad 中重新加载数据之外,-viewDidUnload 还用于释放仍然保留 [self view] 的子视图的属性([self setProperty:nil]),而 [self view] 已经释放,以便它们可以被销毁。我的理解正确吗? - mk12
但是我认为那里的示例代码并没有起作用?因为成员变量myLabel从未保留UILabel(只有视图保留),但它仍在“-viewDidUnload”中释放。或者你是在谈论我之后描述的内容吗?我正在尝试决定的是,对于这种情况(我需要一个成员变量),我是否应该始终使用属性? - mk12
谢谢,我现在明白了。我忘记了alloc会增加retain计数。所以如果我不需要暴露成员变量,我就不需要使用属性。 - mk12

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接