让我们说我正在处理一个有大量视图的应用程序,当UIViewController转向另一个UIViewController时,我在理解内存管理方面遇到了一些问题。
我应该在viewDidDisappear中发布以下哪个对象:?
@property (weak, nonatomic) IBOutlet UIImageView *background;
@property (strong,nonatomic) UILabel *playerLevel;
- (void)viewDidLoad
{
[super viewDidLoad];
map = [[MapView alloc]init];
[self.view addSubview:map];
}
这是正确的方法吗?
- (void)viewDidDisappear:(BOOL)animated
{
[super viewDidDisappear:YES];
[_background removeFromSupeview];
[self.playerLevel removeFromSupeview];
[map removeFromSupeview];
_background = nil;
self.playerLevel = nil;
map = nil;
}
答案 0 :(得分:4)
你不需要做任何事情。 ARC 将为您实施dealloc
方法,该方法将调用您保留属性的所有版本。
我真的建议你阅读apple的内存管理文档,这将有助于理解 ARC 的确在做什么,包括了解如何避免保留周期。
答案 1 :(得分:1)
您不需要发布任何内容。在取消分配视图控制器时,ARC将负责处理它。
答案 2 :(得分:1)
viewDidDisappear
:仅通知视图控制器其视图已从视图层次结构中删除。这是一个可选方法,当视图确实消失时,您的视图可以利用该方法执行自定义代码。所有视图将由ARC自动发布。
答案 3 :(得分:0)
当您设置(显示/推送到新场景)时,先前视图控制器的视图通常不发布。仅当视图控制器被解除/弹出(或者您调用解除segue)时,它才会被解除分配。如果您看到内存消耗继续增长,请确保您正在展示/推动前进,但请关闭/弹出/展开以返回到先前呈现的视图控制器。
(很久以前,在内存不足的情况下,iOS会卸载/发布当前不可见的视图,但Apple在iOS 6.0中不赞成使用它,因为它只是没有节省太多内存并且给开发人员带来了太多问题。 )
一句话,因为您使用的是ARC,所以根本不需要这种viewDidDisappear
方法。当取消分配视图时,它会消除它在子视图上维护的任何强引用,从而导致它们自动被释放(假设您没有在其他地方创建其他强引用,无论如何您都不应该这样做)。同样,当取消分配视图控制器时,它的所有strong
引用也会被解析,从而导致这些属性被释放。
另外,视图控制器维护strong
对顶级view
的引用,但不需要维护strong
对该视图的子视图的引用。调用addSubview
时,顶级视图会维护自己对其子视图的强引用。因此视图控制器拥有视图,但视图拥有其子视图。
此代码示例表明存在一些逻辑上的不一致,IBOutlet
为weak
(应该如此),但您的标签(可能是map
)是{{1 }}。这不会导致问题,但建议对象所有权图中的逻辑不一致。
我可能会建议strong
属性(和playerLevel
,大概)map
引用(就像weak
一样)。并且,如果以编程方式实例化这些,您可以执行以下操作:
IBOutlet
因此,我们创建一个本地@property (weak, nonatomic) UILabel *playerLevel;
- (void)viewDidLoad {
[super viewDidLoad];
UILabel *playerLevel = ...
[self.view addSubview:playerLevel];
self.playerLevel = playerLevel;
}
变量,对其进行配置,将其添加到子视图,然后设置UILabel
属性以引用该标签。在处理weak
属性时,使用该局部变量很重要,因此在您有机会调用weak
之前不会释放它。