5

我目前正在使用集合视图和可区分的数据源开发一个简单的 IOS 应用程序。

每次更新源数据时,我都会初始化视图控制器配置中的所有内容并调用 reloadView 函数。

一旦我调用 reloadView 函数,应用程序就会崩溃并出现以下错误。但前提是集合视图之前是空的。如果那里已经有物品,那么一切都很好。

Assertion failure in -[_UICollectionCompositionalLayoutSolver _queryClientForSectionDefintionForSectionIndex:]


Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Invalid section definition. Please specify a valid section definition when content is to be rendered for a section. This is a client error.'

这就是我的代码的样子:


private func configureHierarchy() {

        let layout = collectionViewHelper.createLayout(structure: self.structure)

        collectionView = UICollectionView(frame: view.bounds, collectionViewLayout: layout)
        collectionView.delegate = self

        collectionView.register(RecentCollectionViewCell.self, forCellWithReuseIdentifier: RecentCollectionViewCell.reuseIdentifier)
        collectionView.register(OverviewCollectionViewCell.self, forCellWithReuseIdentifier: OverviewCollectionViewCell.reuseIdentifier)
        collectionView.register(MessageItemCollectionViewCell.self, forCellWithReuseIdentifier: MessageItemCollectionViewCell.reuseIdentifier)
        view.addSubview(collectionView)
    }

private func configureDataSource() {

        dataSource = UICollectionViewDiffableDataSource<SectionType, Int>(collectionView: collectionView) {
            (collectionView: UICollectionView, indexPath: IndexPath, cellIndex: Int) -> UICollectionViewCell? in

            let sectionItem = self.structure[indexPath.section]

            switch sectionItem.type{
                //Returns a collection view cell of the specific type
            case .recent:
                return getRecentItemCell(...)
            case .overview:
                return getOverviewItemCell(...)
            case .message:
                return getMessageItemCell(...)
            default:
                return nil
            }
        }
    }

我像这样应用快照

private func applySnapshot(structure:[SectionItem]) {
        var snapshot = NSDiffableDataSourceSnapshot<SectionType, Int>()
        var itemOffset = 0

        for structurItem in structure {
            snapshot.appendSections([structurItem.type])
            snapshot.appendItems(Array(itemOffset..<itemOffset + structurItem.items))
            itemOffset += structurItem.items
        }

        dataSource.apply(snapshot, animatingDifferences: false)
    }

我在我的配置中这样做了一次

structure = createStructure()
configureHierarchy()
configureDataSource()
applySnapshot(structure: createStructure())

这是我每次数据变化时调用的reload函数(如果之前没有显示数据就会报错)

func reloadView() {
        structure = createStructure()
        applySnapshot(structure: structure)
    }

任何想法为什么会这样?已经非常感谢了!

4

6 回答 6

2

就我而言, UICollectionViewCompositionalLayout 不会在内存中删除,当我的控制器已被删除时它会继续工作。

private func configureLayout() {
    let layout = UICollectionViewCompositionalLayout { [weak self] (sectionIndex: Int, layoutEnvironment: NSCollectionLayoutEnvironment) -> NSCollectionLayoutSection? in
        return self?.layoutSection(sectionIndex: sectionIndex, layoutEnvironment: layoutEnvironment)
    }
    self.collectionView.collectionViewLayout = layout
}

这是我的代码

于 2020-07-02T13:41:13.467 回答
1

这是 int _UICollectionCompositionalLayoutSolver!它与您的 diffable 数据源无关。您可能还没有完成可组合布局的实现。这就是我刚刚发生的事情:) 这恰好是触发异常的地方。

于 2020-06-18T21:49:56.700 回答
1

就我而言,我的数据源设置错误。我返回的部分比我在UICollectionViewCompositionalLayout(sectionProvider: sectionProvider).

于 2021-04-26T06:33:05.130 回答
1

与 Khoren 的回答类似,在我的情况下,我的实现中存在内存泄漏。我有另一个对象实现并持有对数据源的引用,而不是视图控制器持有对数据源的引用。这最终导致了循环内存引用(内存泄漏)。

解决方案是当视图控制器被关闭时(可能在 viewDidDisappear 上),我设置了 datasource = nil; 因此,打破循环引用循环并避免此错误。

于 2020-09-23T17:42:59.277 回答
0

我在调用时遇到了类似的崩溃,不知何故我返回的旧部分reloadData()关闭了。UICollectionViewCompositionalLayout(sectionProvider:)

我如何修复它collectionView.collectionViewLayout.invalidateLayout()在重新加载之前调用。

于 2022-01-17T09:22:52.413 回答
0

在这个函数中 private func applySnapshot(structure:[SectionItem]) 使用 applySnapshot 和 sectionIdentifier

于 2022-01-12T12:11:07.357 回答