[英]Dequeue cells more than default UICollectionView dequeued cells
官方 Apple 示例代码展示了一种您可能会发现有用的技术。 您可以观察滚动并根据contentOffset
值,而不是依赖UICollectionView
来接收回调并根据需要加载数据,您将知道需要多少向前看。
如果将来的读者无法使用链接,请在此处复制粘贴相关部分。 所有这些都存在于UICollectionViewController
子类中——它通常可以适应任何UIScrollView
。
func scrollViewDidScroll(_ scrollView: UIScrollView) {
// This is your trigger point
updateCachedAssets()
}
var fetchResult: PHFetchResult<PHAsset>!
fileprivate let imageManager = PHCachingImageManager()
fileprivate let thumbnailSize: CGSize = CGSize(width: 100, height: 100)
fileprivate var previousPreheatRect = CGRect.zero
fileprivate func updateCachedAssets() {
// Update only if the view is visible.
guard isViewLoaded && view.window != nil else { return }
// The window you prepare ahead of time is twice the height of the visible rect.
let visibleRect = CGRect(origin: collectionView!.contentOffset, size: collectionView!.bounds.size)
let preheatRect = visibleRect.insetBy(dx: 0, dy: -0.5 * visibleRect.height)
// Update only if the visible area is significantly different from the last preheated area.
let delta = abs(preheatRect.midY - previousPreheatRect.midY)
guard delta > view.bounds.height / 3 else { return }
// Compute the assets to start and stop caching.
let (addedRects, removedRects) = differencesBetweenRects(previousPreheatRect, preheatRect)
let addedAssets = addedRects
.flatMap { rect in collectionView!.indexPathsForElements(in: rect) }
.map { indexPath in fetchResult.object(at: indexPath.item) }
let removedAssets = removedRects
.flatMap { rect in collectionView!.indexPathsForElements(in: rect) }
.map { indexPath in fetchResult.object(at: indexPath.item) }
// Update the assets the PHCachingImageManager is caching.
imageManager.startCachingImages(for: addedAssets,
targetSize: thumbnailSize, contentMode: .aspectFill, options: nil)
imageManager.stopCachingImages(for: removedAssets,
targetSize: thumbnailSize, contentMode: .aspectFill, options: nil)
// Store the computed rectangle for future comparison.
previousPreheatRect = preheatRect
}
fileprivate func differencesBetweenRects(_ old: CGRect, _ new: CGRect) -> (added: [CGRect], removed: [CGRect]) {
if old.intersects(new) {
var added = [CGRect]()
if new.maxY > old.maxY {
added += [CGRect(x: new.origin.x, y: old.maxY,
width: new.width, height: new.maxY - old.maxY)]
}
if old.minY > new.minY {
added += [CGRect(x: new.origin.x, y: new.minY,
width: new.width, height: old.minY - new.minY)]
}
var removed = [CGRect]()
if new.maxY < old.maxY {
removed += [CGRect(x: new.origin.x, y: new.maxY,
width: new.width, height: old.maxY - new.maxY)]
}
if old.minY < new.minY {
removed += [CGRect(x: new.origin.x, y: old.minY,
width: new.width, height: new.minY - old.minY)]
}
return (added, removed)
} else {
return ([new], [old])
}
}
- 该代码已有数年历史,您需要根据自己的要求对其进行调整。
- 您可以将 preheatRect 计算调整为适合您的需求。
// The window you prepare ahead of time is twice the height of the visible rect. let visibleRect = CGRect(origin: collectionView!.contentOffset, size: collectionView!.bounds.size) let preheatRect = visibleRect.insetBy(dx: 0, dy: -0.5 * visibleRect.height)
- 该示例实现了这个
preheatRect
逻辑来预加载PHAsset
缩略图。 您需要将您的数据源调整为类似的样式并开始/停止加载您的资源。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.