我对在基于Nib的UIViewController
s中发生的事情感到有些困惑。生成UIViewController
子类时,模板在viewDidUnload
方法中包含非常具体的注释:
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
这适用于哪些子视图?
viewDidLoad
初始化的那些? (我会说是的)initWithNibName
初始化的那些? (我会说不)如果我像这样使用视图控制器:
MyViewController *controller = [[MyViewController alloc] initWithNibName:@"MyViewController" bundle:nil];
[self.navigationController pushViewController:controller animated:YES];
[controller release];
在这种情况下,我认为持有对子视图的引用的实例变量是否在viewDidUnload
或dealloc
中发布并不重要,因为dealloc
应该在视图中立即调用控制器从堆栈中弹出,所以我不如Apple所说,并在viewDidUnload
而不是dealloc
上发布实例变量。
但是假设我使用MyViewController
作为可以多次推送的实例变量:
if(self.myViewController == nil) {
self.myViewController = [[MyViewController alloc] initWithNibName:@"MyViewController" bundle:nil];
}
//Change some state which should be reflected in the view
self.myViewController.someProperty = someValue;
[self.navigationController pushViewController:self.myViewController animated:YES];
如果我在MyViewController
发布IBOutlet,viewDidUnload
会发生什么?我可以指望在下一个viewDidLoad
上添加新的参考资料吗?
换句话说:viewDidUnload
之后视图本身会发生什么?如果再次按下控制器,是否从Nib释放并重新加载?或者视图是否留在内存中?如果是这样,那么在viewDidLoad
之前重新设置出口?
如果视图保留在内存中且出口在viewDidLoad
之前重新设置或每次按下控制器时重新加载,我认为在viewDidUnload
中释放出口是正确的(即使在第一种情况下也没关系)。但除此之外(特别是如果视图保留在内存中且未重置插件),在viewDidUnload
中发布子视图对于我提供的用例是错误的,我是否正确?
答案 0 :(得分:7)
来自UIViewController documentation,内存管理部分:
当发生内存不足警告时,
UIViewController
类会清除其视图,如果它知道它可以重新加载或稍后再次重新创建它们。如果发生这种情况,它还会调用viewDidUnload
方法,让您的代码有机会放弃与视图层次结构相关联的任何对象的所有权,包括使用nib文件加载的对象,在{{1}中创建的对象方法,以及在运行时延迟创建并添加到视图层次结构中的对象。通常,如果视图控制器包含出口(包含viewDidLoad
关键字的属性或原始变量),则应使用IBOutlet
方法放弃对这些出口的所有权或任何其他与视图无关的数据需要更久。
因此,您不仅可以在viewDidUnload
中发布您的商店,这是首选和推荐的方式。
是的,在调用viewDidUnload
时,您可以指望您的商店指向有效对象。再次从UIViewController文档,viewDidLoad
:
在视图控制器将其关联的视图加载到内存后调用此方法。