iOS 10 collectionView:prefetchItemsAt 未调用

Posted

技术标签:

【中文标题】iOS 10 collectionView:prefetchItemsAt 未调用【英文标题】:iOS 10 collectionView:prefetchItemsAt not called 【发布时间】:2016-07-12 10:26:34 【问题描述】:

我正在尝试UICollectionViewDataSourcePrefetching 协议的新collectionView:prefetchItemsAtcollectionView:cancelPrefetchingForItemsAt 方法,但它们都没有被调用。委托是通过接口构建器设置的(从具有相同结果的代码中尝试),部署目标设置为 ios 10,所以理论上它应该可以工作。所以我的问题是我是否遗漏了一些东西以使其工作,或者机制比我想象的更复杂,系统不认为它应该进行预取?

【问题讨论】:

是否将名为prefetchingEnabledUICollectionView 属性设置为YES?刚刚在 Xcode 8.0 beta 4 中尝试过这个案例 - 按预期工作。 @RomanErmolov 是的,它被设置为true,但没有效果。仅供参考,我使用的是 Swift 理论上,语言根本不重要。我可以猜测您没有不可见的单元格 - 如果所有单元格都在屏幕上,则不会调用此方法。 最后一次尝试:您是否设置了prefetchDataSourceUICollectionView 属性? 您找到解决方案了吗?似乎集合视图的预取仅在您的单元格具有固定大小时才有效。太糟糕了。 【参考方案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开发 如何适配iOS10

iOS - 如何适配iOS10(插曲)

iOS 8、iOS 9、iOS 10 和 iOS 11 上的 UITabBar 的高度是多少?

iOS:Xcode8以下真机测试iOS10.0和iOS10.1配置包

iOS10适配相关

iOS 9 和 iOS 10 CoreData 同时