0

我在类似聊天的 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 出列,设置用于“天”的标题标签以及基于日期的上一条消息的间距。之后,我调用单元格的配置方法,在其中格式化并显示消息文本,或者使用 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

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

4

1 回答 1

0

Caching 'estimatedHeightForRowAt' is almost meaningless in your case, it's called only when UITableView reloads (because it is a feature to improve loading time for UITableView, not for cells). There are a few solutions I can see:

  • avoid using automatic cell heights
  • calculate height for each cell manually (and return in 'heightForRowAt'); then cache those values in the dictionary, like you do it in the code sample for 'estimated height'. I've improved the FPS from 14 to stable 48-60 in my case (there's an extremely complicated layout).
  • if your fps is still bad, try to configure cells asynchronously when scrolling, and synchronously when tableview reloads.

Note: pay attention to recalculate heights when your cell content is changed

于 2018-10-22T11:56:56.760 回答