如何解决优化 UICollectionView 插入和更新
我有一个使用 firebase 的聊天应用程序,每次用户接收或发送消息时,我都会插入一个单元格并更新上一个单元格。但是,它非常缓慢且滞后。如您所见 here,执行批量更新需要很长时间。我发了 10 条短信,耗时 4.16 秒。
我花了很长时间试图弄清楚为什么需要这么长时间,但似乎无法弄清楚。
我有一个 firebase 监听器,每次在聊天中添加帖子时,我都会这样做:
self.collectionView.performBatchUpdates {
self.collectionView.insertSections(IndexSet(integer: self.posts.count - 1))
self.collectionView.reloadSections(IndexSet(integer: self.posts.count - 2))
} completion: { (bool) in
self.collectionView.scrollToItem(at: IndexPath(row: 0,section: self.posts.count - 1),at: .bottom,animated: false)
}
(我更新上一个单元格以查看最后一个帖子是否来自同一用户,以便我可以将帖子粘贴在一起)
数据源:
//MARK: - Datasource
extension ChatController {
override func collectionView(_ collectionView: UICollectionView,numberOfItemsInSection section: Int) -> Int {
return 1
}
override func numberOfSections(in collectionView: UICollectionView) -> Int {
return isFiltering ? filteredPosts.count : posts.count
}
func collectionView(_ collectionView: UICollectionView,layout collectionViewLayout: UICollectionViewLayout,referenceSizeForHeaderInSection section: Int) -> CGSize {
if section == 0 {return CGSize(width: UIScreen.main.bounds.width,height: 50)}
if isFiltering {
if filteredPosts[section].createdAt - filteredPosts[section - 1].createdAt > 3600000 {
return CGSize(width: UIScreen.main.bounds.width,height: 15)
}
if filteredPosts[section - 1].isLastPostInARowFromUser {
return CGSize(width: UIScreen.main.bounds.width,height: -16)
} else {
return CGSize(width: UIScreen.main.bounds.width,height: -31)
}
} else {
if posts[section].createdAt - posts[section - 1].createdAt > 3600000 {
return CGSize(width: UIScreen.main.bounds.width,height: 15)
}
if posts[section - 1].isLastPostInARowFromUser {
return CGSize(width: UIScreen.main.bounds.width,height: -31)
}
}
}
override func collectionView(_ collectionView: UICollectionView,viewForSupplementaryElementOfKind kind: String,at indexPath: IndexPath) -> UICollectionReusableView {
if kind == UICollectionView.elementKindSectionHeader {
let sectionHeader = collectionView.dequeueReusableSupplementaryView(ofKind: kind,withReuseIdentifier: headerReuseIdentifier,for: indexPath) as! TimeStampCollectionViewHeader
let createdAt = isFiltering ? filteredPosts[indexPath.section].createdAt : posts[indexPath.section].createdAt
let date = Date(timeIntervalSince1970: TimeInterval(createdAt/1000))
let startOfToday = Calendar.current.startOfDay(for: Date()).timeIntervalSince1970 * 1000
let startOfYesterday = Calendar.current.startOfDay(for: Date()).timeIntervalSince1970 * 1000 - (3600000 * 24)
let startOfDayOneWeekAgo = Calendar.current.startOfDay(for: Date()).timeIntervalSince1970 * 1000 - (3600000 * 24 * 7)
let dateformat = DateFormatter()
if createdAt > Int(startOfToday) {
dateformat.dateFormat = "h:mm a"
sectionHeader.timeStampLabel.text = "Today \(dateformat.string(from: date))"
} else if createdAt > Int(startOfYesterday) {
dateformat.dateFormat = "h:mm a"
sectionHeader.timeStampLabel.text = "Yesterday \(dateformat.string(from: date))"
} else if createdAt > Int(startOfDayOneWeekAgo) {
dateformat.dateFormat = "EEEE h:mm a"
sectionHeader.timeStampLabel.text = " \(dateformat.string(from: date))"
} else {
dateformat.dateFormat = "E,MMM,dd h:mm a"
sectionHeader.timeStampLabel.text = dateformat.string(from: date)
}
return sectionHeader
} else {
return UICollectionReusableView()
}
}
func collectionView(_ collectionView: UICollectionView,minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return 0
}
func collectionView(_ collectionView: UICollectionView,minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
return 0
}
override func collectionView(_ collectionView: UICollectionView,cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier,for: indexPath) as! PostCell
if isFiltering {
cell.post = filteredPosts[indexPath.section]
} else {
cell.post = posts[indexPath.section]
}
cell.chatController = self
cell.delegate = self
return cell
}
}
//MARK: - UICollectionViewDelegateFlowLayoutz
extension ChatController: UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView,insetForSectionAt section: Int) -> UIEdgeInsets {
return .init(top: 16,left: 0,bottom: 16,right: 0)
}
func collectionView(_ collectionView: UICollectionView,sizeForItemAt indexPath: IndexPath) -> CGSize {
let frame = CGRect(x: 0,y: 0,width: view.frame.width,height: 50)
let estimatedSizeCell = PostCell(frame: frame)
if isFiltering {
estimatedSizeCell.post = filteredPosts[indexPath.section]
} else {
estimatedSizeCell.post = posts[indexPath.section]
}
estimatedSizeCell.layoutIfNeeded()
let targetSize = CGSize(width: view.frame.width,height: 1000)
let estimateSize = estimatedSizeCell.systemLayoutSizeFitting(targetSize)
return .init(width: view.frame.width,height: estimateSize.height)
}
}
这是我的 PostCell 类的链接。它又长又乱,肯定有问题。 https://github.com/SebastianDanson/PostCell/blob/main/PostCell.swift
我对编码比较陌生,任何帮助将不胜感激!
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。