iOS 10 collectionView:prefetchItemsAt 未调用
Posted
技术标签:
【中文标题】iOS 10 collectionView:prefetchItemsAt 未调用【英文标题】:iOS 10 collectionView:prefetchItemsAt not called 【发布时间】:2016-07-12 10:26:34 【问题描述】:我正在尝试UICollectionViewDataSourcePrefetching
协议的新collectionView:prefetchItemsAt
和collectionView:cancelPrefetchingForItemsAt
方法,但它们都没有被调用。委托是通过接口构建器设置的(从具有相同结果的代码中尝试),部署目标设置为 ios 10,所以理论上它应该可以工作。所以我的问题是我是否遗漏了一些东西以使其工作,或者机制比我想象的更复杂,系统不认为它应该进行预取?
【问题讨论】:
是否将名为prefetchingEnabled
的UICollectionView
属性设置为YES
?刚刚在 Xcode 8.0 beta 4 中尝试过这个案例 - 按预期工作。
@RomanErmolov 是的,它被设置为true
,但没有效果。仅供参考,我使用的是 Swift
理论上,语言根本不重要。我可以猜测您没有不可见的单元格 - 如果所有单元格都在屏幕上,则不会调用此方法。
最后一次尝试:您是否设置了prefetchDataSource
的UICollectionView
属性?
您找到解决方案了吗?似乎集合视图的预取仅在您的单元格具有固定大小时才有效。太糟糕了。
【参考方案1】:
您可能正在设置estimatedItemSize,在这种情况下可能不会调用预取。 来源:在一个迷你演示应用中试用。
【讨论】:
你拯救了我的一天,谢谢 yes 将其设置为 none 似乎会使回调被调用。【参考方案2】:在你的 ViewController 中实现 UICollectionViewDataSourcePrefetching 接口:
class ViewController: UIViewController, UICollectionViewDataSourcePrefetching
override func viewDidLoad()
super.viewDidLoad()
collectionView.delegate = self
collectionView.dataSource = self
collectionView.prefetchDataSource = self
您必须检查集合视图属性是否启用了“isPrefetching”。如果未启用,请将其值设置为 true。
collectionView.isPrefetchingEnabled = true
【讨论】:
【参考方案3】:来自docs:
集合视图不会立即为它需要的单元格调用此方法,因此您的代码不能依赖此方法来加载数据
【讨论】:
【参考方案4】:从您的ViewController
中的协议UICollectionViewDataSourcePrefetching
继承:
class ViewController: UIViewController, UICollectionViewDataSourcePrefetching
在情节提要中将以下委托设置到您的集合视图(请参见附图),或者以编程方式进行。
override func viewDidLoad()
super.viewDidLoad()
collectionView.delegate = self
collectionView.dataSource = self
collectionView.prefetchDataSource = self
参考这个例子:https://github.com/Be-With-Viresh/CollectionViewWithPrefetch
【讨论】:
【参考方案5】:override func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath)
//给这个函数添加代码
self.collectionView(collectionView, prefetchItemsAt: [indexPath])
【讨论】:
【参考方案6】:流式布局
将估计大小设置为除none
之外的任何值会导致默认流布局不为我调用预取方法。这是一个示例回调:
func collectionView(_ collectionView: UICollectionView, prefetchItemsAt indexPaths: [IndexPath])
print(indexPaths.map $0.row )
注意在这里设置这个,实际上是在隐式创建的流布局上设置的,而不是实际的UICollectionView
:
这可以使用 Apple 的示例代码进行验证,将其更改为 none
以外的任何内容会导致它不调用委托。
https://developer.apple.com/documentation/uikit/uicollectionviewdatasourceprefetching/prefetching_collection_view_data
组合布局
另一方面,它也可以与组合布局一起使用,因为它们没有 estimatedSize
属性,就像在 IB 中自动创建的默认流布局一样。如果您创建组合布局,它将替换默认的流布局,因此如果您设置组合布局,则在 IB 中设置该属性将不起作用。
组合布局示例:
func createCompositionalLayout() -> UICollectionViewLayout
let itemSize = NSCollectionLayoutSize(
widthDimension: .fractionalWidth(1.0),
heightDimension: .fractionalHeight(1.0)
)
let item = NSCollectionLayoutItem(layoutSize: itemSize)
let groupSize = NSCollectionLayoutSize(
widthDimension: .fractionalWidth(1.0),
heightDimension: .fractionalWidth(1/5)
)
let group = NSCollectionLayoutGroup.horizontal(
layoutSize: groupSize,
subitem: item,
count: 1
)
let section = NSCollectionLayoutSection(group: group)
return UICollectionViewCompositionalLayout(section: section)
然后这样设置:
collectionView.collectionViewLayout = createCompositionalLayout()
在viewDidLoad
委托中。
这样做确实允许调用prefetchItemsAt
方法。
还发现,如果在组合布局上估计单元格高度,则它不起作用。这很糟糕。
UICollectionView: compositional layout disables prefetching?
似乎如果您的任何 layoutSize 对象具有估计尺寸,它就会在预取时退出。
let size = NSCollectionLayoutSize(widthDimension: .estimated(104),
heightDimension: .estimated(128))
return NSCollectionLayoutItem(layoutSize: size)
【讨论】:
以上是关于iOS 10 collectionView:prefetchItemsAt 未调用的主要内容,如果未能解决你的问题,请参考以下文章
iOS 8、iOS 9、iOS 10 和 iOS 11 上的 UITabBar 的高度是多少?