【问题标题】:Determine when UITableViewCell is deallocated确定何时释放 UITableViewCell
【发布时间】:2013-04-08 20:22:26
【问题描述】:

我在我的应用程序中使用核心数据以及NSFetchedResultsController 来填充表格。我的数据库有 40k+ 个条目,所以表很长。每个表格单元格都有一个使用SDWebImage 从Web 加载的缩略图。如果我慢慢滚动,一切都会很好,如果我在几秒钟内开始快速滚动,我会崩溃。

NSZombies 没有显示任何有用的东西。

我猜它与SDWebImage 和从网络加载有关。 SDWebImage 的工作方式是在后台加载图像,然后在完成下载后设置下载的图像(罗嗦)。我的想法是UITableView 正在释放单元格,然后SDWebImage 尝试在释放的单元格上设置图像。因此,如果我可以确定何时释放UITableViewCell,我可以停止SDWebImage 下载过程并希望解决问题。

我已经尝试添加

- (void)dealloc {
    NSLog(@"dealloc");
}

捕捉单元格何时被释放但我什么也没得到。

编辑 我在子类 UITableViewCell 中有我的 -(void)dealloc 方法。

编辑 这是我创建单元格的位置/方式

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
 {
 static NSString* inventoryCellID = @"InventoryCustomCellID";

 InventoryCustomCell* cell = (InventoryCustomCell *)[tableView dequeueReusableCellWithIdentifier:inventoryCellID forIndexPath:indexPath];

 [self configureCell:cell atIndexPath:indexPath];

 return cell;
 }


- (void)configureCell:(InventoryCustomCell *)cell atIndexPath:(NSIndexPath *)indexPath {

    [cell formatCellWithProduct:[fetchedResultsController objectAtIndexPath:indexPath] enableAdding:NO];

    cell.openThumbnailButton.tag = indexPath.row;

    [cell.openThumbnailButton addTarget:self action:@selector(presentThumbnailViewWithCell:) forControlEvents:UIControlEventTouchUpInside];
}

在我的自定义单元格中,这是被调用的配置方法:

- (void)formatCellWithProduct:(Product*)product enableAdding:(bool)addingEnabled {

    self.titleLabel.text = product.part_number;
    self.partNumberLabel.text = [[[product.manufacturer allObjects] objectAtIndex:0] name];

    //The SDWebImage UIImageView category method
    [self.thumbImageView setImageWithURL:[NSURL URLWithString:product.photo] placeholderImage:[UIImage imageNamed:@"icon.png"]];
}

编辑 这是下载图像并设置它的 SDWebImage 方法。

- (void)setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options progress:(SDWebImageDownloaderProgressBlock)progressBlock completed:(SDWebImageCompletedBlock)completedBlock;
{
    [self cancelCurrentImageLoad];

    self.image = placeholder;

    if (url)
    {
        __weak UIImageView *wself = self;
        id<SDWebImageOperation> operation = [SDWebImageManager.sharedManager downloadWithURL:url options:options progress:progressBlock completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished)
        {
            __strong UIImageView *sself = wself;
            if (!sself) return;
            if (image)
            {
                sself.image = image;
                [sself setNeedsLayout];
            }
            if (completedBlock && finished)
            {
                completedBlock(image, error, cacheType);
            }
        }];
        objc_setAssociatedObject(self, &operationKey, operation, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    }
}

【问题讨论】:

  • 仪器告诉你什么?
  • 它进行了一些挖掘,但发现“setImageWithURL”上的完成块正在发送到一个已释放的实例。所以我的假设是正确的,我需要找到一种方法来通知单元格正在被 TableView 释放
  • 请发布该块。由于单元重用,您不应指望单元的解除分配
  • @vikingosegundo 我已经更新了下载块

标签: objective-c memory-management uitableview


【解决方案1】:

表格视图不太倾向于分配和取消分配表格视图单元格。创建单元格的成本很高,因此它们会在可能的情况下被重复使用,而不是在它们离开屏幕时被丢弃。

UITableViewDelegate 方法 -tableView:didEndDisplayingCell:forRowAtIndexPath: 是更新单元格以取消下载或其他不再相关的操作的更好地方。

看起来,每次调用-setImageWithURL:etc:etc: 都在尝试取消之前对该图像视图的下载。

【讨论】:

  • 当tableview被释放时,单元格不会被释放吗?
【解决方案2】:

你没有解释你把dealloc方法放在哪里..

我认为您可以尝试向您的视图控制器添加一个类别以进行调试,只是为了测试您的单元格的释放是否被调用(不是您的子类UITableviewCell)。

例如:

@implementation UITableViewCell(Dealloc)

 - (void)dealloc {
   NSLog(@"dealloc");
   [super dealloc];
 }

@end

您使用 ARC 吗?如果没有,你忘了

InventoryCustomCell* cell = (InventoryCustomCell *)[[tableView dequeueReusableCellWithIdentifier:inventoryCellID forIndexPath:indexPath] autorelease];

【讨论】:

  • 我已经更新了我的问题,但我在 UITableViewCell 的子类中有 dealloc 方法
  • 请显示cellForRow..方法
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-08-21
  • 2010-11-22
  • 2023-03-25
  • 2015-05-08
  • 2019-05-27
相关资源
最近更新 更多