调用 reloadData 时自定义 UITableViewCell 内存泄漏

Posted

技术标签:

【中文标题】调用 reloadData 时自定义 UITableViewCell 内存泄漏【英文标题】:custom UITableViewCell memory leak when calling reloadData 【发布时间】:2014-06-09 09:24:16 【问题描述】:

我有一个加载一些自定义 UITableViewCells 的 UITableView。这些自定义单元格分配一些 UIButton,并将这些按钮添加到自定义单元格的 contentView。在 tableView 上重复调用 reloadData 时,这些 UIButton 似乎正在慢慢泄漏内存。我正在使用 ARC,ios 7。

这里是创建单元格的地方:

- (UITableViewCell *)tableView:(UITableView *)_tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
    static NSString *simpleTableIdentifier = @"PostCell";
    PostCell *cell = [_tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
    if (cell == nil) 
        cell = [[PostCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpleTableIdentifier];
    
    return cell;

这是自定义单元格的 init 方法:

- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier 
    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
    if (self) 
        self.height = 0;
        self.backgroundColor = [UIColor clearColor];
        self.selectionStyle = UITableViewCellSelectionStyleNone;
        [self addInteractionContainer];
    
    return self;

最后是 addInteractionContainer 方法(如果我不调用这个方法,我看不到泄漏):

- (void)addInteractionContainer 
    //interaction container
    UIView* interactionContainer = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.frame.size.width, 80)];
    [interactionContainer setBackgroundColor:[UIColor ProseSepiaColor]];

    //like button
    LikeButton* likeButton = [[LikeButton alloc] initWithFrame:CGRectMake(10, 10, 75, 30) liked:([post.yourVote intValue] > 0)];
    [likeButton addTarget:self action:@selector(likePost:) forControlEvents:UIControlEventTouchUpInside];
    [interactionContainer addSubview:likeButton];

    //comment button
    CommentButton* commentButton = [[CommentButton alloc] initWithFrame:CGRectMake(likeButton.frame.origin.x + likeButton.frame.size.width + 10,
                                                           10, 105, 30)];
    [commentButton addTarget:self action:@selector(segueToComments:) forControlEvents:UIControlEventTouchUpInside];
    [commentButton setNumComments:self.post.numComments];
    [interactionContainer addSubview:commentButton];
    [self.contentView addSubview:interactionContainer];
    self.height += interactionContainer.frame.size.height;

【问题讨论】:

正如您所说,当您不调用 addInteractionContainer 时,您不会泄漏。您可以使用 UIButton 进行测试,以便我们可以确认 Like 按钮类或评论类的子类化有问题 您可以使用泄漏工具来尝试识别问题,但您的 addInteractionContainer 看起来并不“正确”。它正在添加事件处理程序并引用数据 - “self.post.numComments”,即使此时无法设置此属性。您应该在单元格构造函数中添加 UI 元素并通过属性公开这些元素。然后,您可以在 tableview 控制器中添加操作处理程序和内容 我确实尝试过只使用一个基本的 UIButton 而没有额外的数据,同样的问题发生了。 【参考方案1】:
try this
- (UITableViewCell *)tableView:(UITableView *)_tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
    static NSString *simpleTableIdentifier = @"PostCell";
    PostCell *cell = [_tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
    if(cell!=nil)

     cell=nil;

    if (cell == nil) 
        cell = [[PostCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpleTableIdentifier];
    
    return cell;

【讨论】:

以上是关于调用 reloadData 时自定义 UITableViewCell 内存泄漏的主要内容,如果未能解决你的问题,请参考以下文章

UITableView 没有在 reloadData 上重新加载

使用 NSFetchedRequestController 更新 UITableView 行和部分,而不使用 reloadData

使用 UITableView 的可变高度自定义单元格调用 reloadData 时保持 UITableView 的当前位置

调用 reloadData 后防止标头更新?

除非调用 reloadData,否则图像无法正确加载

collectionview reloadData时如何自定义UICollectionView过渡动画?