没有自动布局的可变TableViewCell高度

问题描述

我有一个基于UITableView的超古老的Objective-C聊天代码。单元格只有一种类型,我们称之为ChatTableViewCell。在我们的聊天中,有10多种消息类型(文本,图像,事件等)。 ChatTableViewCell本身负责一堆逻辑,例如:

  • 在哪一侧显示头像(传入或传出消息);
  • 隐藏头像,如果它是来自同一用户的第二条以上消息(消息分组);
  • 对带有表情符号的消息的反应(用户可以对任何类型的消息做出反应)
  • 显示外发邮件传递状态的标签; –等等。

ChatTableViewCell还包含一个容器视图,其中将所需的UIView子类(ImageMessageViewTextMessageViewEventMessageView添加为子视图。 / p>

func tableView(_ tableView: UITableView,cellForRowAt indexPath: IndexPath) -> UITableViewCell 方法消息通过其索引从消息数组中获取今天之前,每个消息对象将包含所有信息,这些消息将像消息文本一样显示在单元格中,或者,例如,如果是事件消息,它将包含所有信息项,例如位置名称,时间,日期,接受回复的人数等。

聊天代码是一种极端的传统,完全没有在任何地方使用自动布局。 每个像元高度由 - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath 在此方法中,消息通过其索引获取,并且取决于消息的类型,该消息将传递到所需的UIView子类的静态方法(嵌入到ChatTableViewCell中)。这些静态方法的人工高度计算很丑陋,如下所示:

+ (CGSize)neededSizeforContentWithEventInfo:(SBEventInfo *)eventInfo
{
    CGFloat contentHeight = 0;
    
    UILabel *label = [SBEventBubbleView labelForType:LabelTypeIcon];
    label.text = @"?";
    CGRect frame = [SBEventBubbleView frameForLabelText:label];
    contentHeight += frame.size.height;
    
    label = [SBEventBubbleView labelForType:LabelTypeTitle];
    label.text = eventInfo.name;
    frame = [SBEventBubbleView frameForLabelText:label];
    contentHeight += frame.size.height;
    
    label = [SBEventBubbleView labelForType:LabelTypeTime];
    label.text = eventInfo.time;
    frame = [SBEventBubbleView frameForLabelText:label];
    contentHeight += frame.size.height;
    
    label = [SBEventBubbleView labelForType:LabelTypeAddress];
    label.text = eventInfo.address;
    frame = [SBEventBubbleView frameForLabelText:label];
    contentHeight += frame.size.height;
    
    contentHeight += kEventBubblePaddingTop + kEventBubblePaddingBottom;
    
    contentHeight += (kEventBubbleContaineRSSpace + kEventBubbleButtonHeight);
    
    return CGSizeMake([SBEventBubbleView maxWidth],contentHeight);
}

+ (CGRect)frameForLabelText:(UILabel *)label
{
    return [label.text boundingRectWithSize:CGSizeMake([SBEventBubbleView maxWidth] - kEventBubblePaddingLeft - kEventBubblePaddingRight,MAXFLOAT) options:NsstringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName:label.font} context:nil];
}

问题:

现在有一种新型消息,它不包含所有信息。相反,它仅包含一些ID,该ID传递给UIView的相应子类,然后在该视图内部进行网络调用,该调用使用此ID来获取所有信息。有了这个异步调用,就不可能使用丑陋的老式方法和静态方法来计算此消息在屏幕上的高度。

在这种情况下我该怎么办?是否可以从

返回一些临时/虚拟高度
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath```

然后,当单元中的网络呼叫完成时,以某种方式重新计算具有所有可用数据的单元的高度?

再一次,所有这些代码都是完全基于帧的,不幸的是,根本没有使用 AutoLayout。。否则,这将是一个小问题。 / p>

任何帮助将不胜感激!如果您想提供帮助,请询问更多信息,但对问题不完全了解。

解决方法

我不知道如何获得数据。但是我认为您同步或异步获取的任何数据都可以用于计算,它只需要回调就可以告诉控制器我已经拥有数据,并且您需要重置像元高度。那是我的主意。 enter image description here

enter image description here

,

image = image.cuda().transpose(1,3)中,返回您尚无数据行的估计高度。连续提取数据后,调用tableView(_:heightForRowAt:)

当表格视图重新加载该行时,它将再次调用tableView.reloadRows(at:with:)委托方法,您可以返回适当的高度。