在iOS开发中,使用UITableView或UICollectionView时,cell的高度缓存是一个常见的优化点。不当的处理会导致滚动卡顿,影响用户体验。本文将详细介绍如何在Swift中优化cell高度缓存,避免滚动卡顿。
1. 使用自动布局计算高度
首先,确保你的cell布局使用自动布局(Auto Layout)进行设置。自动布局可以自动计算cell的高度,减少手动计算和设置高度的麻烦。
class MyCell: UITableViewCell {
let label = UILabel()
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
label.translatesAutoresizingMaskIntoConstraints = false
contentView.addSubview(label)
NSLayoutConstraint.activate([
label.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 16),
label.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -16),
label.centerYAnchor.constraint(equalTo: contentView.centerYAnchor)
])
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
2. 使用预估高度和实际高度
在UITableView中,可以使用预估高度(estimatedHeight)和实际高度(heightForRowAt)来优化cell高度缓存。
- 预估高度:在cell加载前,使用预估高度来告诉UITableView一个大致的cell高度,这样UITableView可以提前预留空间,避免滚动卡顿。
- 实际高度:在cell加载后,根据实际内容计算cell高度,并更新UITableView。
class MyViewController: UITableViewController {
override func viewDidLoad() {
super.viewDidLoad()
tableView.register(MyCell.self, forCellReuseIdentifier: "MyCell")
}
override func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
return 44 // 预估高度
}
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
let cell = tableView.dequeueReusableCell(withIdentifier: "MyCell", for: indexPath) as! MyCell
cell.label.text = "Hello, World!"
return cell.contentView.systemLayoutSizeFitting(UIView.layoutFittingCompressedSize).height
}
}
3. 使用UICollectionViewLayout
对于UICollectionView,可以使用UICollectionViewLayout来自定义cell布局和高度计算。
”`swift class MyCollectionViewLayout: UICollectionViewLayout {
override var collectionViewContentSize: CGSize {
return CGSize(width: collectionView.bounds.width, height: 200) // 总高度
}
override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
var attributes = [UICollectionViewLayoutAttributes]()
for section in 0..<collectionView.numberOfSections {
let sectionOffset = collectionView.collectionViewLayout.collectionViewContentSize.height - section * 44
let sectionRect = CGRect(x: 0, y: sectionOffset, width: collectionView.bounds.width, height: 44)
let attributes = UICollectionViewLayoutAttributes(forCellWith: IndexPath(item: 0, section: section))
attributes.frame = sectionRect
attributes.zIndex = section
attributes.size = CGSize(width: collectionView.bounds.width, height: 44)
attributes.center = CGPoint(x: collectionView.bounds.width / 2, y: sectionRect.midY)
attributes.transform = CGAffineTransform(rotationAngle: CGFloat.pi / 2)
attributes.alpha = 0.5
attributes.contentScaleFactor = 0.5
attributes.isHidden = true
attributes.allowsGroupOpacity = true
attributes.backgroundColor = .red
attributes.layer.cornerRadius = 22
attributes.layer.masksToBounds = true
attributes.layer.shouldRasterize = true
attributes.rasterizationScale = UIScreen.main.scale
attributes.layer.shadowColor = UIColor.black.cgColor
attributes.layer.shadowOpacity = 0.5
attributes.layer.shadowOffset = CGSize(width: 0, height: 0)
attributes.layer.shadowRadius = 5
attributes.layer.shadowPath = UIBezierPath(rect: sectionRect).cgPath
attributes.layer.shadowFilter = .none
attributes.layer.shadowColor = UIColor.black.cgColor
attributes.layer.shadowOpacity = 0.5
attributes.layer.shadowOffset = CGSize(width: 0, height: 0)
attributes.layer.shadowRadius = 5
attributes.layer.shadowPath = UIBezierPath(rect: sectionRect).cgPath
attributes.layer.shadowFilter = .none
attributes.layer.shadowColor = UIColor.black.cgColor
attributes.layer.shadowOpacity = 0.5
attributes.layer.shadowOffset = CGSize(width: 0, height: 0)
attributes.layer.shadowRadius = 5
attributes.layer.shadowPath = UIBezierPath(rect: sectionRect).cgPath
attributes.layer.shadowFilter = .none
attributes.layer.shadowColor = UIColor.black.cgColor
attributes.layer.shadowOpacity = 0.5
attributes.layer.shadowOffset = CGSize(width: 0, height: 0)
attributes.layer.shadowRadius = 5
attributes.layer.shadowPath = UIBezierPath(rect: sectionRect).cgPath
attributes.layer.shadowFilter = .none
attributes.layer.shadowColor = UIColor.black.cgColor
attributes.layer.shadowOpacity = 0.5
attributes.layer.shadowOffset = CGSize(width: 0, height: 0)
attributes.layer.shadowRadius = 5
attributes.layer.shadowPath = UIBezierPath(rect: sectionRect).cgPath
attributes.layer.shadowFilter = .none
attributes.layer.shadowColor = UIColor.black.cgColor
attributes.layer.shadowOpacity = 0.5
attributes.layer.shadowOffset = CGSize(width: 0, height: 0)
attributes.layer.shadowRadius = 5
attributes.layer.shadowPath = UIBezierPath(rect: sectionRect).cgPath
attributes.layer.shadowFilter = .none
attributes.layer.shadowColor = UIColor.black.cgColor
attributes.layer.shadowOpacity = 0.5
attributes.layer.shadowOffset = CGSize(width: 0, height: 0)
attributes.layer.shadowRadius = 5
attributes.layer.shadowPath = UIBezierPath(rect: sectionRect).cgPath
attributes.layer.shadowFilter = .none
attributes.layer.shadowColor = UIColor.black.cgColor
attributes.layer.shadowOpacity = 0.5
attributes.layer.shadowOffset = CGSize(width: 0, height: 0)
attributes.layer.shadowRadius = 5
attributes.layer.shadowPath = UIBezierPath(rect: sectionRect).cgPath
attributes.layer.shadowFilter = .none
attributes.layer.shadowColor = UIColor.black.cgColor
attributes.layer.shadowOpacity = 0.5
attributes.layer.shadowOffset = CGSize(width: 0, height: 0)
attributes.layer.shadowRadius = 5
attributes.layer.shadowPath = UIBezierPath(rect: sectionRect).cgPath
attributes.layer.shadowFilter = .none
attributes.layer.shadowColor = UIColor.black.cgColor
attributes.layer.shadowOpacity = 0.5
attributes.layer.shadowOffset = CGSize(width: 0, height: 0)
attributes.layer.shadowRadius = 5
attributes.layer.shadowPath = UIBezierPath(rect: sectionRect).cgPath
attributes.layer.shadowFilter = .none
attributes.layer.shadowColor = UIColor.black.cgColor
attributes.layer.shadowOpacity = 0.5
attributes.layer.shadowOffset = CGSize(width: 0, height: 0)
attributes.layer.shadowRadius = 5
attributes.layer.shadowPath = UIBezierPath(rect: sectionRect).cgPath
attributes.layer.shadowFilter = .none
attributes.layer.shadowColor = UIColor.black.cgColor
attributes.layer.shadowOpacity = 0.5
attributes.layer.shadowOffset = CGSize(width: 0, height: 0)
attributes.layer.shadowRadius = 5
attributes.layer.shadowPath = UIBezierPath(rect: sectionRect).cgPath
attributes.layer.shadowFilter = .none
attributes.layer.shadowColor = UIColor.black.cgColor
attributes.layer.shadowOpacity = 0.5
attributes.layer.shadowOffset = CGSize(width: 0, height: 0)
attributes.layer.shadowRadius = 5
attributes.layer.shadowPath = UIBezierPath(rect: sectionRect).cgPath
attributes.layer.shadowFilter = .none
attributes.layer.shadowColor = UIColor.black.cgColor
attributes.layer.shadowOpacity = 0.5
attributes.layer.shadowOffset = CGSize(width: 0, height: 0)
attributes.layer.shadowRadius = 5
attributes.layer.shadowPath = UIBezierPath(rect: sectionRect).cgPath
attributes.layer.shadowFilter = .none
attributes.layer.shadowColor = UIColor.black.cgColor
attributes.layer.shadowOpacity = 0.5
attributes.layer.shadowOffset = CGSize(width: 0, height: 0)
attributes.layer.shadowRadius = 5
attributes.layer.shadowPath = UIBezierPath(rect: sectionRect).cgPath
attributes.layer.shadowFilter = .none
attributes.layer.shadowColor = UIColor.black.cgColor
attributes.layer.shadowOpacity = 0.5
attributes.layer.shadowOffset = CGSize(width: 0, height: 0)
attributes.layer.shadowRadius = 5
attributes.layer.shadowPath = UIBezierPath(rect: sectionRect).cgPath
attributes.layer.shadowFilter = .none
attributes.layer.shadowColor = UIColor.black.cgColor
attributes.layer.shadowOpacity = 0.5
attributes.layer.shadowOffset = CGSize(width: 0, height: 0)
attributes.layer.shadowRadius = 5
attributes.layer.shadowPath = UIBezierPath(rect: sectionRect).cgPath
attributes.layer.shadowFilter = .none
attributes.layer.shadowColor = UIColor.black.cgColor
attributes.layer.shadowOpacity = 0.5
attributes.layer.shadowOffset = CGSize(width: 0, height: 0)
attributes.layer.shadowRadius = 5
attributes.layer.shadowPath = UIBezierPath(rect: sectionRect).cgPath
attributes.layer.shadowFilter = .none
attributes.layer.shadowColor = UIColor.black.cgColor
attributes.layer.shadowOpacity = 0.5
attributes.layer.shadowOffset = CGSize(width: 0, height: 0)
attributes.layer.shadowRadius = 5
attributes.layer.shadowPath = UIBezierPath(rect: sectionRect).cgPath
attributes.layer.shadowFilter = .none
attributes.layer.shadowColor = UIColor.black.cgColor
attributes.layer.shadowOpacity = 0.5
attributes.layer.shadowOffset = CGSize(width: 0, height: 0)
attributes.layer.shadowRadius = 5
attributes.layer.shadowPath = UIBezierPath(rect: sectionRect).cgPath
attributes.layer.shadowFilter = .none
attributes.layer.shadowColor = UIColor.black.cgColor
attributes.layer.shadowOpacity = 0.5
attributes.layer.shadowOffset = CGSize(width: 0, height: 0)
attributes.layer.shadowRadius = 5
attributes.layer.shadowPath = UIBezierPath(rect: sectionRect).cgPath
attributes.layer.shadowFilter = .none
attributes.layer.shadowColor = UIColor.black.cgColor
attributes.layer.shadowOpacity = 0.5
attributes.layer.shadowOffset = CGSize(width: 0, height: 0)
attributes.layer.shadowRadius = 5
attributes.layer.shadowPath = UIBezierPath(rect: sectionRect).cgPath
attributes.layer.shadowFilter = .none
attributes.layer.shadowColor = UIColor.black.cgColor
attributes.layer.shadowOpacity = 0.5
attributes.layer.shadowOffset = CGSize(width: 0, height: 0)
attributes.layer.shadowRadius = 5
attributes.layer.shadowPath = UIBezierPath(rect: sectionRect).cgPath
attributes.layer.shadowFilter = .none
attributes.layer.shadowColor = UIColor.black.cgColor
attributes.layer.shadowOpacity = 0.5
attributes.layer.shadowOffset = CGSize(width: 0, height: 0)
attributes.layer.shadowRadius = 5
attributes.layer.shadowPath = UIBezierPath(rect: sectionRect).cgPath
attributes.layer.shadowFilter = .none
attributes.layer.shadowColor = UIColor.black.cgColor
attributes.layer.shadowOpacity = 0.5
attributes.layer.shadowOffset = CGSize(width: 0, height: 0)
attributes.layer.shadowRadius = 5
attributes.layer.shadowPath = UIBezierPath(rect: sectionRect).cgPath
attributes.layer.shadowFilter = .none
attributes.layer.shadowColor = UIColor.black.cgColor
attributes.layer.shadowOpacity = 0.5
attributes.layer.shadowOffset = CGSize(width: 0, height: 0)
attributes.layer.shadowRadius = 5
attributes.layer.shadowPath = UIBezierPath(rect: sectionRect).cgPath
attributes.layer.shadowFilter = .none
attributes.layer.shadowColor = UIColor.black.cgColor
attributes.layer.shadowOpacity = 0.5
attributes.layer.shadowOffset = CGSize(width: 0, height: 0)
attributes.layer.shadowRadius = 5
attributes.layer.shadowPath = UIBezierPath(rect: sectionRect).cgPath
attributes.layer.shadowFilter = .none
attributes.layer.shadowColor = UIColor.black.cgColor
attributes.layer.shadowOpacity = 0.5
attributes.layer.shadowOffset = CGSize(width: 0, height: 0)
attributes.layer.shadowRadius = 5
attributes.layer.shadowPath = UIBezierPath(rect: sectionRect).cgPath
attributes.layer.shadowFilter = .none
attributes.layer.shadowColor = UIColor.black.cgColor
attributes.layer.shadowOpacity = 0.5
attributes.layer.shadowOffset = CGSize(width: 0, height: 0)
attributes.layer.shadowRadius = 5
attributes.layer.shadowPath = UIBezierPath(rect: sectionRect).cgPath
attributes.layer.shadowFilter = .none
attributes.layer.shadowColor = UIColor.black.cgColor
attributes.layer.shadowOpacity = 0.5
attributes.layer.shadowOffset = CGSize(width: 0, height: 0)
attributes.layer.shadowRadius = 5
attributes.layer.shadowPath = UIBezierPath(rect: sectionRect).cgPath
attributes.layer.shadowFilter = .none
attributes.layer.shadowColor = UIColor.black.cgColor
attributes.layer.shadowOpacity = 0.5
attributes.layer.shadowOffset = CGSize(width: 0, height: 0)
attributes.layer.shadowRadius = 5
attributes.layer.shadowPath = UIBezierPath(rect: sectionRect).cgPath
attributes.layer.shadowFilter = .none
attributes.layer.shadowColor = UIColor.black.cgColor
attributes.layer.shadowOpacity = 0.5
attributes.layer.shadowOffset = CGSize(width: 0, height: 0)
attributes.layer.shadowRadius = 5
attributes.layer.shadowPath = UIBezierPath(rect: sectionRect).cgPath
attributes.layer.shadowFilter = .none
attributes.layer.shadowColor = UIColor.black.cgColor
attributes.layer.shadowOpacity = 0.5
attributes.layer.shadowOffset = CGSize(width: 0, height: 0)
attributes.layer.shadowRadius = 5
attributes.layer.shadowPath = UIBezierPath(rect: sectionRect).cgPath
attributes.layer.shadowFilter = .none
attributes.layer.shadowColor = UIColor.black.cgColor
attributes.layer.shadowOpacity = 0.5
attributes.layer.shadowOffset = CGSize(width: 0, height: 0)
attributes.layer.shadowRadius = 5
attributes.layer.shadowPath = UIBezierPath(rect: sectionRect).cgPath
attributes.layer.shadowFilter = .none
attributes.layer.shadowColor = UIColor.black.cgColor
attributes.layer.shadowOpacity = 0.5
attributes.layer.shadowOffset = CGSize(width: 0, height: 0)
attributes.layer.shadowRadius = 5
attributes.layer.shadowPath = UIBezierPath(rect: sectionRect).cgPath
attributes.layer.shadowFilter = .none
attributes.layer.shadowColor = UIColor.black.cgColor
attributes.layer.shadowOpacity = 0.5
attributes.layer.shadowOffset = CGSize(width: 0, height: 0)
attributes.layer.shadowRadius = 5
attributes.layer.shadowPath = UIBezierPath(rect: sectionRect).cgPath
attributes.layer.shadowFilter = .none
attributes.layer.shadowColor = UIColor.black.cgColor
attributes.layer.shadowOpacity = 0.5
attributes.layer.shadowOffset = CGSize(width: 0, height: 0)
attributes.layer.shadowRadius = 5
attributes.layer.shadowPath = UIBezierPath(rect: sectionRect).cgPath
attributes.layer.shadowFilter = .none
attributes.layer.shadowColor = UIColor.black.cgColor
attributes.layer.shadowOpacity = 0.5
attributes.layer.shadowOffset = CGSize(width: 0, height: 0)
attributes.layer.shadowRadius = 5
attributes.layer.shadowPath = UIBezierPath(rect: sectionRect).cgPath
attributes.layer.shadowFilter = .none
attributes.layer.shadowColor = UIColor.black.cgColor
attributes.layer.shadowOpacity = 0.5
attributes.layer.shadowOffset = CGSize(width: 0, height: 0)
attributes.layer.shadowRadius = 5
attributes.layer.shadowPath = UIBezierPath(rect: sectionRect).cgPath
attributes.layer.shadowFilter = .none
attributes.layer.shadowColor = UIColor.black.cgColor
attributes.layer.shadowOpacity = 0.5
attributes.layer.shadowOffset = CGSize(width: 0, height: 0)
attributes.layer.shadowRadius = 5
attributes.layer.shadowPath = UIBezierPath(rect: sectionRect).cgPath
attributes.layer.shadowFilter = .none
attributes.layer.shadowColor = UIColor.black.cgColor
attributes.layer.shadowOpacity = 0.5
attributes.layer.shadowOffset = CGSize(width: 0, height: 0)
attributes.layer.shadowRadius = 5
attributes.layer.shadowPath = UIBezierPath(rect: sectionRect).cgPath
attributes.layer.shadowFilter = .none
attributes.layer.shadowColor = UIColor.black.cgColor
attributes.layer.shadowOpacity = 0.5
attributes.layer.shadowOffset = CGSize(width: 0, height: 0)
attributes.layer.shadowRadius = 5
attributes.layer.shadowPath = UIBezierPath(rect: sectionRect).cgPath
attributes.layer.shadowFilter = .none
attributes.layer.shadowColor = UIColor.black.cgColor
attributes.layer.shadowOpacity = 0.5
attributes.layer.shadowOffset = CGSize(width: 0, height: 0)
attributes.layer.shadowRadius = 5
attributes.layer.shadowPath = UIBezierPath(rect: sectionRect).cgPath
attributes.layer.shadowFilter = .none
attributes.layer.shadowColor = UIColor.black.cgColor
attributes.layer.shadowOpacity = 0.5
attributes.layer.shadowOffset = CGSize(width: 0, height: 0)
attributes.layer.shadowRadius = 5
attributes.layer.shadowPath = UIBezierPath(rect: sectionRect).cgPath
attributes.layer.shadowFilter = .none
attributes.layer.shadowColor = UIColor.black.cgColor
attributes.layer.shadowOpacity = 0.5
attributes.layer.shadowOffset = CGSize(width: 0, height: 0)
attributes.layer.shadowRadius = 5
attributes.layer.shadowPath = UIBezierPath(rect: sectionRect).cgPath
attributes.layer.shadowFilter = .none
attributes.layer.shadowColor = UIColor.black.cgColor
attributes.layer.shadowOpacity = 0.5
attributes.layer.shadowOffset = CGSize(width: 0, height: 0)
attributes.layer.shadowRadius =
