UITableView 内存问题

Posted

技术标签:

【中文标题】UITableView 内存问题【英文标题】:UITableView memory issues 【发布时间】:2014-05-30 17:26:47 【问题描述】:

我在我的UITableView 的一些单元格中添加UIView。我使用dequeueReusableCellWithIdentifier,似乎当我上下滚动时,视图永远不会从内存中删除,它会不断在已经加载的视图前面添加新视图。它永远增加了内存,这不是它应该的方式。

不显示时如何从内存中删除这些UIViews

else if (indexPath.row == 0 && !isPremium) 
        // Google AdMob
        adCell = [tableView dequeueReusableCellWithIdentifier:adCellId];
        if (adCell == nil) 
            adCell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:adCellId];
        

        AdMobView = [[GADBannerView alloc]initWithAdSize:kGADAdSizeSmartBannerPortrait];
        AdMobView.adUnitID = @"ca-app-pub-XXXXXXXXXXXXXXX";
        AdMobView.rootViewController = self;
        AdMobView.autoresizingMask = UIViewAutoresizingFlexibleWidth;

        // load the ads
        GADRequest *request = [GADRequest request];
        request.testDevices = [NSArray arrayWithObjects:GAD_SIMULATOR_ID, @"XXXXXXXXX", nil]; // COMMENT THIS LINE WHEN IN PROD

        // add gps
        if ([latitude length] > 2 && [longitude length] > 2) 
            [request setLocationWithLatitude:[latitude floatValue] longitude:[longitude floatValue] accuracy:50]; // accuracy [m]
        

        adCell.backgroundColor = [UIColor colorWithRed:247.0/255.0 green:149.0/255.0 blue: 24.0/255.0 alpha:1];
        if (!AdMobView.superview) 
            [AdMobView loadRequest:request];
        
        AdMobView.tag = 3000;
        [adCell.contentView addSubview:AdMobView];

        [adCell setSelectionStyle:UITableViewCellSelectionStyleNone];

        return adCell;

【问题讨论】:

没有代码无法诊断,您可以添加您的代码吗? 非常好的问题。你有什么证据?你如何证明细胞没有被重复使用?如果你是对的,那是因为你的 identifier: 与单元格标识符不匹配。 顺便说一下,这里有一些示例代码,向您展示如何跟踪单元格是否被重用:github.com/mattneub/Programming-ios-Book-Examples/blob/master/… 我添加了一个 alpha = 0.2 的 UIImageView。当我向上和向下滚动时,它会变暗,这意味着它再次在前一张图片前面添加了一张新图片。 确实非常好:您已经检测到问题并很好地解释了问题。请参阅下面的答案。 【参考方案1】:

如果单元格被重复使用但视图仍在堆积,那是因为在您的cellForRowAtIndexPath: 中,您正在添加视图甚至是已经具有该视图的回收单元格。因此,随着您向上和向下滚动,视图的数量会不断增加,并在每个单元格中相互叠加。

因此(现在您已经添加了一些代码)您在说:

[adCell.contentView addSubview:AdMobView];

...对于每个单元格,无条件。但是如果一个单元格被重用,它就已经有了一个 AdMobView!您需要检查这一点,以便仅有条件地添加此子视图(对于您添加的任何其他子视图也是如此)。

【讨论】:

看,例如,我的这段代码:github.com/mattneub/Programming-iOS-Book-Examples/blob/master/… 我使用tag 来标记添加的子视图,以确保我不会再次添加它并在以下情况下进行不同的配置它已经存在于重复使用的单元格中。 在此处进一步查看我的讨论:apeth.com/iOSBook/ch21.html#_adding_subviews_in_code 我添加了这个:if (adCell.contentView.tag != 3000) [adCell.contentView addSubview:AdMobView]; adCell.contentView.tag = 3000; ,它解决了这个问题。 @matt 的好回答。 这很聪明,没有法律规定你不能通过给内容视图一个标签来标记单元格。但它过于僵化。我建议您更仔细地模仿我在我指向您的代码中所做的 - 将标签 添加到 AdMobView 并询问内容视图是否有任何带有该标签的子视图。

以上是关于UITableView 内存问题的主要内容,如果未能解决你的问题,请参考以下文章

UITableView 和 NSFetchedResultsController 的内存泄漏

UITableView 自定义 Cells,滚动和内存管理

UITableView 和 UINavigationController 中的内存管理

iOS:滚动 UITableView 时应用程序崩溃/内存被填充

来自调试器的消息:在 UITableView/UICollectionView 中使用 gif 图像 Kingfisher 库滚动时因内存问题而终止

NSNotificationCenter ,打印内存地址