重用的 tableView 单元格不调用 layoutSubviews 方法

Posted

技术标签:

【中文标题】重用的 tableView 单元格不调用 layoutSubviews 方法【英文标题】:Reused tableView cells not calling layoutSubviews method 【发布时间】:2014-08-02 01:54:44 【问题描述】:

我有一个自定义 tableViewCell 类,在我的 tableView 单元格中我有一个自定义 UIView。每个 tableView 单元格都与一个唯一的UIBezierPath 相关联,该UIBezierPath 设置为等于视图path 属性。为了呈现路径,必须调用layoutSubviews。我注意到我的前 5 个单元格调用了 layoutSubviews,但接下来的 5 个单元格没有调用 layoutSubviews,因此它们的路径最终不会被渲染,它们最终只是重用了前 5 个单元格的路径。由于后 5 个单元格只是重复使用前 5 个单元格,我如何为每个单元格调用 layOutSubviews

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


    static NSString* identifier = @"audioTableCell";

    OSAudioTableCell *cell = [self.audioTable dequeueReusableCellWithIdentifier:identifier];

    if(cell == nil)
    
         cell = [[OSAudioTableCell alloc] initWithStyle: UITableViewCellStyleDefault reuseIdentifier: identifier];
    

        Recording * recording = [self.managedDocument.frc objectAtIndexPath:indexPath];
        cell.waveView.path = nil;
        cell.waveView.minAmpl = [recording.minAmpl floatValue];
        NSData * pathData = recording.waveData;

        //Setting the path 
        cell.waveView.path = [NSKeyedUnarchiver unarchiveObjectWithData:pathData];
        [cell setImageSize:cell.waveView.bounds.size];
 

//这是我的自定义 UIView 类 waveView 中第一个被调用的方法

-(void) layoutSubviews


    if (!self.blueWave) 

         self.blueWave = [self createShapeLayer];

         self.blueWave.strokeColor = [UIColor colorWithRed:107/255.0f green:212/255.0f blue:231/255.0f alpha:1.0f].CGColor;

        self.redWave = [self createShapeLayer];
        self.redWave.strokeColor = [UIColor redColor].CGColor;
        self.redWave.strokeEnd = self.progress;

        [self.layer addSublayer:self.blueWave];
        [self.layer insertSublayer:self.redWave above:self.blueWave];

        [self render];

    

     

【问题讨论】:

打电话给[super layoutSubviews]很重要 我会在哪里称呼它? 作为 layoutSubviews 的第一行。 @rmaddy 实现了它,但没有任何区别。如果我调用 [self.waveView layoutSubviews];在cellForRowAtIndexPath 中,它将调用每个单元格的方法,这很好。但是,第二组 5 个单元格将分别呈现正确的路径以及它们正在重用的单元格的路径。 永远不要直接调用 layoutSubviews。 【参考方案1】:

因此,无论我尝试什么,layOutSubviews 都不会被我重复使用的单元格调用。我试图将 UIView 路径设置为 nil 然后调用 setNeedsLayout 但这没有任何作用。我尝试清除prepareForReuse 中的路径,但仍然没有运气。我必须做的是在重复使用单元格时手动删除CAShapeLayers。成功了。

if(cell == nil)

    cell = [[OSAudioTableCell alloc] initWithStyle: UITableViewCellStyleDefault reuseIdentifier: identifier];

else

    [cell.waveView.blueWave removeFromSuperlayer];
    [cell.waveView.redWave removeFromSuperlayer];
    cell.waveView.blueWave = nil;
    cell.waveView.redWave = nil;
    cell.waveView.path = nil;
    cell.trackLabel.text = nil;

【讨论】:

【参考方案2】:

对于现在偶然发现此答案并遇到相同问题的任何人:

我通过将计算层的新路径的函数放在 UICollectionViewCell 类中的 override layoutSubviews() 函数中的单独 DispatchQueue 块中来修复它。

override func layoutSubviews() 
    super.layoutSubviews()
    
    DispatchQueue.main.async 
        self.shapeLayer.path = UIBezierPath(roundedRect: viewBubbleBase.bounds, cornerRadius: bubbleCornerRadius).cgPath
    

【讨论】:

以上是关于重用的 tableView 单元格不调用 layoutSubviews 方法的主要内容,如果未能解决你的问题,请参考以下文章

TableView 多个单元格不起作用,由于信号 9 而终止

TableView 单元格不显示信息

默认的 tableview 单元格不响应暗模式

动画下拉UIView时TableView单元格不改变高度

ios第一个单元格不是从UITableView的顶部开始

具有多个标签的自我调整大小的单元格不显示多行标签