UICollectionView:组合布局禁用预取? [英] UICollectionView: compositional layout disables prefetching?

查看:13
本文介绍了UICollectionView:组合布局禁用预取?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个非常简单的 UICollectionView,它使用组合布局轻松实现动态单元格高度.不幸的是,这样做似乎会禁用使用 UICollectionViewDataSourcePrefetching 的内容预取.在以下示例代码中,collectionView(_:prefetchItemsAt:) 方法仅在集合视图初始显示时调用一次.没有滚动动作会导致对该方法的进一步调用.

I have a very simple UICollectionView that uses compositional layout to easily achieve dynamic cell heights. Unfortunately doing that seems to disable content prefetching using UICollectionViewDataSourcePrefetching. In the following sample code, the collectionView(_:prefetchItemsAt:) method is called only once, upon initial display of the collection view. No scrolling action leads to further calls to the method.

我该怎么做才能使预取工作?

What can I do to get prefetching working?

class ViewController: UIViewController, 
    UICollectionViewDataSource,
    UICollectionViewDelegate,
    UICollectionViewDataSourcePrefetching
{
    @IBOutlet var collectionView: UICollectionView!

    override func viewDidLoad() {
        super.viewDidLoad()

        collectionView.collectionViewLayout = createLayout()
        collectionView.dataSource = self
        collectionView.delegate = self
        collectionView.prefetchDataSource = self
        collectionView.register(MyCell.self, forCellWithReuseIdentifier: "cell")
    }

    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return 100
    }

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! MyCell
        cell.label.text = String(repeating: "(indexPath) ", count: indexPath.item)

        return cell
    }

    // this is only called once. Why?
    func collectionView(_ collectionView: UICollectionView, prefetchItemsAt indexPaths: [IndexPath]) {
        print("prefetch for (indexPaths)")
    }

    private func createLayout() -> UICollectionViewLayout {
        let layout = UICollectionViewCompositionalLayout { (_, _) -> NSCollectionLayoutSection? in

            let size = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0),
                                              heightDimension: .estimated(44))
            let item = NSCollectionLayoutItem(layoutSize: size)

            let group = NSCollectionLayoutGroup.horizontal(layoutSize: size, subitem: item, count: 1)
            group.interItemSpacing = .fixed(16)

            let section = NSCollectionLayoutSection(group: group)
            section.contentInsets = NSDirectionalEdgeInsets(top: 0, leading: 16, bottom: 0, trailing: 16)
            section.interGroupSpacing = 8

            return section
        }

        return layout
    }
}

class MyCell: UICollectionViewCell {
    let label = UILabel()

    override init(frame: CGRect) {
        super.init(frame: frame)

        label.numberOfLines = 0
        label.lineBreakMode = .byWordWrapping
        backgroundColor = .orange
        contentView.addSubview(label)

        label.translatesAutoresizingMaskIntoConstraints = false
        label.topAnchor.constraint(equalTo: contentView.topAnchor).isActive = true
        label.leadingAnchor.constraint(equalTo: contentView.leadingAnchor).isActive = true
        label.trailingAnchor.constraint(equalTo: contentView.trailingAnchor).isActive = true
        label.bottomAnchor.constraint(equalTo: contentView.bottomAnchor).isActive = true
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

}

(使用 Xcode 11.5/iOS 13.5.collectionView 插座连接到情节提要中的全屏实例)

(Using Xcode 11.5 / iOS 13.5. The collectionView outlet is connected to a full-screen instance in a storyboard)

进一步的测试表明 heightDimension: .estimated(44) 似乎是原因.将其替换为 .absolute(44) 可以再次进行预取,但这当然违背了使用多行文本进行这种布局的目的.似乎是一个错误,如果有人想欺骗它,我已经提交了 FB7849272.

Further testing shows that heightDimension: .estimated(44) seems to be the cause. Replacing this with .absolute(44) makes prefetching work again, but that of course defeats the purpose of having such a layout with multi-line text. Seems like a bug, and I've filed FB7849272 if anyone would like to dupe it.

EDIT/2:目前,我可以通过使用普通的旧流布局并计算每个单独的单元格高度来避免这种情况,这也使预取再次工作.不过,我很好奇在仍然使用组合布局的同时是否有解决方法,所以我添加了一个赏金.

EDIT/2: For the time being, I can avoid this situation by using a plain old flow layout and calculate each individual cell height, this also makes prefetching work again. Nevertheless, I'm curious if there isn't a workaround while still using compositional layouts, so I added a bounty.

推荐答案

我刚刚收到 Apple 的反馈,要求我在 Xcode 13.1 中重新测试这个问题,你瞧,这个 bug 确实已经修复了.

I've just received feedback from Apple asking me to re-test this issue in Xcode 13.1, and lo and behold, the bug has indeed been fixed.

这篇关于UICollectionView:组合布局禁用预取?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆