0

编辑

我发现我的屏幕不会为零,因为它们保留了 RefCt 但我的问题是为什么 RefCt 不是 0?我只是创建、添加和删除视图。还添加了仪器的屏幕转储:

仪器屏幕转储

所以你一开始就看到

Malloc 1 initwithframe,retain:2 initwithframe,release:1 -[UIView(Internal) _addSubview:positioned:relativeTo:],retain:2 Quartzcore CALAyer layoutSublayers,retain:3 Quartzcore CALAyer layoutSublayers,release:2 然后在我的代码中删除这个查看,removeFromSuperView:1

有人可以解释一下吗:

 -[UIView(Internal) _addSubview:positioned:relativeTo:], retain : 2

线?我认为这就是为什么我的观点仍然有一个 RefCt。

结尾

我试图清理我的代码并最终加速我的应用程序,但我不认为我真的得到了整个内存管理的东西。基本上,我的应用程序有一个对用户可见的视图,但它可以根据用户在菜单中选择的内容切换到不同的视图。现在我认为最符合逻辑的是一次只分配一个视图并占用内存空间,当用户选择另一个视图时,应该释放当前视图并分配所选视图。在选择新视图时,我尝试通过执行以下操作来创建它:

- (void)removeMenus {
    @autoreleasepool {
        for (UIView *view in container.subviews) {
            NSLog(@"View to be removed: %@", view);
            [view removeFromSuperview];
        }
    }
}

假设用户选择再次显示开始屏幕。这段代码将运行:

- (void)createStartScreen {
    if (startScreen == nil) {
        startScreen = [[StartScreen alloc] initWithFrame:CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height)];
        startScreen.delegate = self;
        startScreen.layer.shadowColor = [[UIColor blackColor] CGColor];
        startScreen.layer.shadowOffset = CGSizeMake(0.0f, 0.0f);
        startScreen.layer.shadowRadius = 5.0f;
        startScreen.layer.shadowOpacity = 1.0f;
    }
}

我在那里放了一个断点,发现 startscreen 不是 nil ,而我认为应该是因为我从 superview 中删除了它(也尝试删除该 var 的指针)。如果我理解正确,startscreen 的保留计数不为零,对吗?我也在使用 ARC,所以我认为 ARC 会很好地处理这个问题。

释放用户不再可见的视图以保留内存的正确方法是什么?

4

2 回答 2

1

如果您想更清楚地了解阻止您的视图被发布的原因,您应该使用 Instruments 的分配模板来分析您的应用程序。这将告诉您每个保留和释放的调用站点,包括由 ARC 和系统框架执行的那些。如果您的视图是从 XIB 文件中实例化的,那么在一定程度上,系统框架会控制它们的生命周期。

我可以提供的下一条明智的建议是现在停止考虑绝对保留计数。只是假装该-retainCount方法不存在。真的。我不是在开玩笑。其他比我更有权威的人已经解释了为什么保留计数无用的细节,所以如果你不相信我的话,请阅读这个

尽管如此,我没有足够的信息来确定,但通常过度使用内存并不是由于一两个视图尚未发布。仪器可以让您了解您的真正问题是什么。

于 2013-06-21T11:04:10.833 回答
1

这取决于 ivarstartScreen是什么。如果startScreen在视图控制器中定义为强 ivar,则分配后它的引用计数为 1,在您将其设置为视图层次结构中的子视图后,引用计数为 2。然后,从其父视图中删除视图只会将 refcount 减少到 1,并且您必须显式地 nil 变量才能释放它。

另一种选择是您的视图在 Storyboard 或 XIB 文件中定义,并通过插座连接到您的视图控制器。在这种情况下,您的视图 ivar 必须设置为弱变量,因为它已经被其他人强烈持有。

在此处阅读强限定符和弱限定符之间的区别。

最后一件事——为了更好的可读性,通常的惯例是在你想要延迟实例化的变量上定义一个属性,然后将你编写的代码放在createStartScreen重写的 getter 方法中。

于 2013-06-21T11:10:34.840 回答