【问题标题】:Memory warrning tableviewcell内存警告表视图单元格
【发布时间】:2013-12-14 03:31:06
【问题描述】:

我在 xib 文件中有两个 tableviewcell,我都使用它们。

当我使用其中一个时,内存仍然是 7.3MB,但是当我同时使用两个时,内存增长得非常快。

请帮助我。我现在不知道出了什么问题。

我的代码如下:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{

    NSUInteger row = [indexPath row];
    NSDictionary *rowData = [self.events objectAtIndex:row];

    static NSString *CellIdentifierL = @"LeftCell";
    static NSString *CellIdentifierR = @"RightCell";


    SampleTableCell *cellLeft = [tableView dequeueReusableCellWithIdentifier:CellIdentifierL];
    SampleTableCell *cellRight = [tableView dequeueReusableCellWithIdentifier:CellIdentifierR];

    if (cellLeft == nil) {
        NSArray* topLevelObjects = [[NSBundle mainBundle] loadNibNamed:@"LeftTableCell" owner:self options:nil];
        for (id currentObject in topLevelObjects) {
            if ([currentObject isKindOfClass:[SampleTableCell class]]) {
                cellLeft = (SampleTableCell *)currentObject;
                break;
            }
        }
    }

    if (cellRight == nil) {
        NSArray* topLevelObjects = [[NSBundle mainBundle] loadNibNamed:@"RightTableCell" owner:self options:nil];
        for (id currentObject in topLevelObjects) {
            if ([currentObject isKindOfClass:[SampleTableCell class]]) {
                cellRight = (SampleTableCell *)currentObject;
                break;
            }
        }
    }



    return (row%2==0)?cellRight:cellLeft;
}

【问题讨论】:

  • 您是否检查了您的内存崩溃报告或仪器日志,因为您的代码看起来不错,您正在使用单元格做什么,我猜您还剩下一些
  • 我认为这段代码没有问题。内存占用何时增长?滚动表格视图时?
  • 两种理论: 1- 你确定你的SampleTableCell 有正确的reusableCellIdentifier 吗? (在你的 xib 中检查)如果没有,这意味着你创建了太多的行。 2-在创建它们之前,您应该确定必须创建哪个单元格。不过,这只对第一个单元格创建很重要。
  • 在使用 2 个单元后,您是否在代码中启用了 Zoombies?
  • 哈!那么你的问题在于强引用: property (nonatomic, strong) IBOutlet UILabel *labelDate;这些 IBOutlet 应该是弱的:property (nonatomic, weak) IBOutlet UILabel *labelDate;

标签: ios objective-c memory-management uitableview


【解决方案1】:

这不是一个好方法。您正在为每一行创建两个单元格,但您只使用其中一个。您还应该使用更新的方法来使用基于 xib 的单元格——即,在 viewDidLoad 中使用 registerNib:forCellWithReuseIdentifier: 来注册两个 nib。首先检查奇数行/偶数行,然后将正确的单元格出列(使用 register 方法时无需检查 nil)。你这样做:

- (void)viewDidLoad {
    [super viewDidLoad];
    [self.tableView registerNib:[UINib nibWithNibName:@"SampleCell1" bundle:nil] forCellReuseIdentifier:@"SampleCell1"];
    [self.tableView registerNib:[UINib nibWithNibName:@"SampleCell2" bundle:nil] forCellReuseIdentifier:@"SampleCell2"];

}


- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

    if (indexPath.row % 2 == 0) {
        SampleCell *cell = [tableView dequeueReusableCellWithIdentifier:@"SampleCell1" forIndexPath:indexPath];
        // populate cell with data
        return cell;
    }else{
        SampleCell *cell = [tableView dequeueReusableCellWithIdentifier:@"SampleCell2" forIndexPath:indexPath];
        // populate cell with data
        return cell;
    }
}

这就是你需要做的。无需检查 nil 单元格,因为 dequeueReusableCellWithIdentifier:forIndexPath: 如果您注册 nib 或在情节提要中制作单元格(在这种情况下不需要注册任何内容),则保证返回有效单元格。

【讨论】:

  • 你有例子吗?我应该在控制器的 viewDidLoad 中创建吗?以及如何在 cellForRowAtIndex 中使用它
  • 创建两个单元格应该不是问题。当方法返回时,ARC 应该立即释放未使用的单元格。尽管在这种情况下将 self 设置为 nib 的所有者是否会抵消 ARC 是一个有趣的问题。您可以在 loadNibNamed: 中不使用 owner:self 的情况下尝试吗?
  • @Unmerciful,我已经更新了我的答案,向您展示如何做到这一点。我为此示例创建了一个类 SampleCell 和两个 xib 文件 SampleCell1 和 SampleCell2。
  • @TamásZahola,是的,你写的是真的——我的解释应该更清楚。我并不是要暗示,制造两个细胞都会导致记忆问题。这不是好的代码,所以不应该那样做。我不知道我的回答是否能解决问题,但它显示了 Apple 建议现在使用基于 xib 的单元格进行表格视图的方式。
【解决方案2】:

我改成这样:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{

    NSUInteger row = [indexPath row];
    NSDictionary *rowData = [self.events objectAtIndex:row];

    SampleTableCell *cell;


    if(row%2==0){

        cell = [[[NSBundle mainBundle] loadNibNamed:@"RightTableCell" owner:self options:nil]objectAtIndex:0];

    }else{
        cell = [[[NSBundle mainBundle] loadNibNamed:@"LeftTableCell" owner:self options:nil]objectAtIndex:0];
    }

    cell.labelName.text = [rowData objectForKey:@"name"];

    return cell;
}

但我不知道这是个好主意吗?

【讨论】:

    【解决方案3】:

    您只需要创建您需要的单元格。你的代码应该是这样的:

    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
    
        NSUInteger row = [indexPath row];
        NSDictionary *rowData = [self.events objectAtIndex:row];
    
        static NSString *CellIdentifierL = @"LeftCell";
        static NSString *CellIdentifierR = @"RightCell";
    
        if (cellLeft == nil) {
            SampleTableCell *cellLeft = [tableView dequeueReusableCellWithIdentifier:CellIdentifierL];
            NSArray* topLevelObjects = [[NSBundle mainBundle] loadNibNamed:@"LeftTableCell" owner:self options:nil];
            for (id currentObject in topLevelObjects) {
                if ([currentObject isKindOfClass:[SampleTableCell class]]) {
                    cellLeft = (SampleTableCell *)currentObject;
                    break;
                }
            }
            return cellLeft;
        }
    
        if (cellRight == nil) {
            SampleTableCell *cellRight = [tableView dequeueReusableCellWithIdentifier:CellIdentifierR];
            NSArray* topLevelObjects = [[NSBundle mainBundle] loadNibNamed:@"RightTableCell" owner:self options:nil];
            for (id currentObject in topLevelObjects) {
                if ([currentObject isKindOfClass:[SampleTableCell class]]) {
                    cellRight = (SampleTableCell *)currentObject;
                    break;
                }
            }
            return cellRight;
        }
    
    
    
        return nil;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-04-07
      • 2023-04-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多