我需要动态计算UICollectionView的单元格高度。我正在使用这个功能
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize
问题是它在显示之前返回每个单元格的大小。如果数组中有120个项目,它将在
之前计算120个单元格大小func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell
被调用。这会产生很大的性能问题。加载整个集合需要10秒钟。如果我不使用sizeforitematindexpath,集合将在1秒内加载。我该如何解决这个问题?
我正在使用Xcode 8.3.3& Swift 3.0
这是第一个代表的确切代码
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let json = JSON(mySources[indexPath.row])
var url = NSURL(string: json["cover"]["source"].stringValue)
var data = NSData(contentsOf: url as! URL)
var photo = UIImage(data: data as! Data)
var height1 = photo?.size.height
var boundingRect = CGRect(x:0, y:0, width: 372, height: CGFloat(MAXFLOAT))
let rect = AVMakeRect(aspectRatio: (photo?.size)!, insideRect: boundingRect)
let imageHeight = rect.height
let font = UIFont(name: "Raleway-SemiBold", size: 17)
let titleHeight = heightForLabel(text: json["name"].stringValue, font: font!, width: 160)
let restaurantHeight = heightForLabel(text: json["place"]["name"].stringValue, font: font!, width: 160)
print(restaurantHeight + titleHeight + imageHeight)
return CGSize(width: 372, height:imageHeight + titleHeight + restaurantHeight + 100)
}
答案 0 :(得分:1)
UICollectionViewFlowLayout
总是一次计算所有细胞的大小。
但是,如果我记得很清楚,你可以通过为其estimatedItemSize
属性设置一个非零值来防止这种情况(文档不清楚):
集合视图中估计的单元格大小。
当单元格动态调整其大小时,提供估计的单元格大小可以提高集合视图的性能。通过指定估计值,集合视图可以推迟确定其内容实际大小所需的一些计算。具体而言,假设不在屏幕上的单元格是估计的高度。
此属性的默认值为CGSizeZero。将其设置为任何其他值会导致集合视图使用单元格的preferredLayoutAttributesFitting(_ :)方法查询每个单元格的实际大小。如果所有单元格的高度相同,请使用itemSize属性而不是此属性来指定单元格大小。
因此,调用下一段代码可能会解决您的性能问题:
(collectionView.collectionViewLayout as? UICollectionViewFlowLayout)?.estimatedItemSize = CGSize(width: 375.0, height: 44.0)
答案 1 :(得分:0)
您应该使用可重复使用的单元格,以便您的集合视图不会一次加载所有数据,而只会加载屏幕上的数据。这比总数少得多。这将节省性能,内存,并将减少CPU使用(图形更平滑,电池消耗更少)。
如何:
为您的collectionView:
menuCollectionView.register(UICollectionViewCell.self, forCellWithReuseIdentifier: "MenuCell")
函数cellForItemAtIndexPath中的:
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "MenuCell", for: indexPath as IndexPath)
return cell
}
希望这有帮助!