【问题标题】:memory retention/leak on iOSiOS上的内存保留/泄漏
【发布时间】:2013-02-09 09:19:23
【问题描述】:

我有一个从 XIB 文件定义的 UItableViewCell。这个单元格包含一个 UIScrollView,它使用 UIView 对象 - viewXY - 动态填充。我在代码中的任何地方都使用 arc。用户界面如下所示:

单元格 0:[view00 view01 view02 ...]

单元格 1:[view10 view11 view12 ...]

etc...,其中 [ ] 是单元格内容,可以水平滚动。

问题:我分析了应用程序,当我垂直滚动向下 时,内存占用量迅速增长,据我所知,它永远不会恢复正常,也不会达到平稳状态。更重要的是,如果我向下滚动几个单元格然后再向上滚动,内存也会增加......

我用仪器工具检查了泄漏,没有。

我围绕创建 viewXY 的代码部分缩小了问题的范围。如果我使用:

myDisplay* viewXY;//myDisplay is a UIView subclass
-->viewXY = [[NSBundle mainBundle] loadNibNamed:AW_UI_VE owner:self options:nil][0];
[scrollView addSubview:viewXY];

当我翻阅单元格时,记忆变得失控。 NIB 是一个简单的 UIView+UIImageView+2 Labels.... 如果我替换说

UIImageView *viewXY = [UIImageView alloc] initWithImage:[blablabla]]
[scrollView addSubview:viewXY];

一切都很好。仪器中的 Live Bytes 迅速达到稳定水平。

作为测试的一部分,我加载 NIB 文件而不执行其自定义类中定义的任何方法,因此它带有 IB 中定义的 IBOutlets(默认标签文本、图像等)。

这东西快把我逼疯了。

欢迎提出建议以了解我做错了什么。

【问题讨论】:

  • 只需检查 XCode 中的方案选项(产品 > 方案 > 编辑方案 > 运行 > 诊断选项卡)并确保您未选中 Enable Zombie Objects (NSZombieEnabled)。

标签: ios memory xcode4.5 nib


【解决方案1】:

我不确定这是否与内存使用有关,但文档推荐 UINib 用于此用例:

只要您的应用程序需要重复实例化相同的 nib 数据,就应该使用 UINib 对象。

另一种可能是myDisplay 中有一个保留周期。它是否有任何应该是weakstrong 属性?

【讨论】:

  • 我考虑过,虽然 *myDisplay 不应该,因为它是在本地创建的。因此,当应用程序离开该功能时,该引用消失,只保留由 [scrollView addSubview:viewXY] 产生的引用。我确实将 viewXY 列表保存在一个数组中,这样我就可以对它们调用 removeFromSuperview 。当它被删除时,指针被手动分配为零。也许我应该定义这个数组只包含弱引用?
【解决方案2】:

在你的 ViewController 的 viewDidLoad 中你应该有这样的东西:

 [yourTable registerNib:[UINib nibWithNibName:@"yourUITableViewCellNibName" bundle:nil]
 forCellReuseIdentifier:@"reuseIdentifier"];

并且在您的表数据源方法(cellForRowAtIndexPath)中,您应该具有以下内容:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
     MyCustomCell* cell = [tableView dequeueReusableCellWithIdentifier:@"reuseIdentifier"];
     //Set your cell's values.

return cell;
}

【讨论】:

    【解决方案3】:
    [scrollView addSubview:viewXY];
    

    你的问题。您正在向滚动视图添加一些内容,并且永远不要删除它。

    从事物的声音来看,您没有正确使用 UITableView。你应该有一个视图控制器,它实现了 UITableViewDelegate 和 UITableViewDataSource 协议中的方法,并使用它们来用数据填充表格。您永远不会直接向表格添加任何内容,您只会在它请求时向其提供单元格。

    【讨论】:

    • 为了清楚起见,我没有包含整个代码,但是在调用 cellsForRownAtIndexPath (UITableViewDataSource) 时会创建单元格。此外,viewXY 是延迟加载的,然后在它离开视图屏幕时使用 removeFromSuperview 将其删除。
    • @Alex 请注意,您不应该只分配单元格,您应该尝试将它们出列并仅在出列失败时分配它们。 (实际上,我相信在 iOS 6 中你可以使用同一个函数调用来做到这两点)
    • 现在担心,就这部分代码而言,我是“按照书本”做的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-03-22
    • 2012-12-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-18
    • 1970-01-01
    相关资源
    最近更新 更多