UITableView动态单元格高度表现

时间:2017-02-04 11:42:32

标签: ios swift uitableview chat uitableviewautomaticdimension

我在类似聊天的UITableview中遇到了性能问题。我有三种类型的细胞:

  • 文字
  • 图像/视频
  • 音频

目前,我正在处理动态单元格高度缓存字典中的大小:

func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
    if let estimatedHeight = self.estimatedMessagesHeights[indexPath] {
        return estimatedHeight
    }
    return UITableViewAutomaticDimension
}

func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
    return UITableViewAutomaticDimension
}

func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
    self.estimatedMessagesHeights.updateValue(cell.bounds.size.height, forKey: indexPath)
}

它工作得不好,也许滚动不是那么迟钝但是当我使用

滚动到UITableView的底部时
self.tblChat.scrollToRow(at: indexPath, at: .bottom, animated: false)

我的应用程序暂时冻结。我尝试为细胞设置静态高度,但没有发生冻结。

在cellForRowAtIndexPath中,我为消息类型出列正确的xib,设置用于" day"的标题标签。和基于日期的上一条消息的间距。之后我调用格式化的单元格的配置方法并显示消息文本,或者使用SDWebImage显示远程/本地图像(必要时下载后)。

let message = self.model.getMessage(atIndex: indexPath.row)
var cell: ChatMessageTableViewCell?

if message.isSender {
    if message.type == .audio {
        cell = self.tblChat.dequeueReusableCell(withIdentifier: self.audioSenderIdentifier, for: indexPath) as! ChatAudioSenderTableViewCell
    } else if message.type == .text {
        cell = self.tblChat.dequeueReusableCell(withIdentifier: self.senderIdentifier, for: indexPath) as! ChatMessageSenderTableViewCell
    } else {
        cell = self.tblChat.dequeueReusableCell(withIdentifier: self.mediaSenderIdentifier, for: indexPath) as! ChatMediaSenderTableViewCell
    }
} else {
    if message.type == .audio {
        cell = self.tblChat.dequeueReusableCell(withIdentifier: self.audioReceiverIdentifier, for: indexPath) as! ChatAudioReceiverTableViewCell
    } else if message.type == .text {
        cell = self.tblChat.dequeueReusableCell(withIdentifier: self.receiverIdentifier, for: indexPath) as! ChatMessageReceiverTableViewCell
    } else {
        cell = self.tblChat.dequeueReusableCell(withIdentifier: self.mediaReceiverIdentifier, for: indexPath) as! ChatMediaReceiverTableViewCell
    }
}

let previousMessage = self.model.getMessage(atIndex: indexPath.row-1)
cell.topLabel.text = self.model.getMessageDayTitle(message: message, previousMessage: previousMessage)
cell.cntTopSpacing.constant = self.model.getSpacingBetweenMessages(previousMessage: previousMessage, message: message)
cell.configure(withMessage: message, chat: self.model.chat)

cell?.delegate = self

return cell

有关如何正确处理单元格高度计算的任何建议?

1 个答案:

答案 0 :(得分:0)

在您的情况下,缓存'estimatedHeightForRowAt'几乎是没有意义的,仅在重新加载UITableView时才调用它(因为这是缩短UITableView而不是单元格的加载时间的功能)。我可以看到一些解决方案:

  • 避免使用自动像元高度
  • 手动计算每个单元格的高度(并返回“ heightForRowAt”);然后将这些值缓存在字典中,就像在代码示例中为“估计高度”所做的那样。在我的情况下,我已经将FPS从14提高到稳定的48-60(布局非常复杂)。
  • 如果fps仍然很差,请尝试在滚动时异步配置单元格,并在重新加载tableview时同步配置。

注意:更改单元格内容时,请注意重新计算高度