标签: uicollectionviewdiffabledatasource

在集合视图中应用包含所有新数据的快照后,可比较数据源滚动到顶部

我有一个集合视图(使用组合布局和可比较数据源),其标题中有一个分段控件。当控制值发生变化时,单元格会更新为UICollectionViewCell包含所有新数据的不同类。它基本上按预期工作。问题是当我应用快照时,我的集合视图滚动回顶部。我怎样才能让它不滚动?

当我的视图加载时调用:

    func initialDataSourceSetUp() {
        var snapshot = NSDiffableDataSourceSnapshot<Section, SampleDataObject>()
        snapshot.appendSections([.main])
        snapshot.appendItems(sampleData)
        sampleDataSource.apply(snapshot, animatingDifferences: true, completion: nil)
    }
Run Code Online (Sandbox Code Playgroud)

当分段控件发生变化时调用:

    func updateDataSource() {
        var snapshotSectionMain = sampleDataSource.snapshot(for: .main)
        snapshotSectionMain.deleteAll()
        if currentSegment == 0 {
            snapshotSectionMain.append(sampleData)
        } else {
            snapshotSectionMain.append(sampleData2)
        }
        sampleDataSource.apply(snapshotSectionMain, to: .main)
    }
Run Code Online (Sandbox Code Playgroud)

设置我的单元格和补充视图:

        sampleDataSource = UICollectionViewDiffableDataSource(collectionView: collectionView, cellProvider: { (collectionView, indexPath, item) -> UICollectionViewCell? in
            if self.currentSegment == 0 {
                let cell = collectionView.dequeueReusableCell(withReuseIdentifier: BasicRentalItemCollectionViewCell.identifier, for: indexPath) as! BasicRentalItemCollectionViewCell
                cell.imageMain.image = item.image
                cell.labelTitle.text = item.title
                return cell …
Run Code Online (Sandbox Code Playgroud)

ios uicollectionview nsdiffabledatasourcesnapshot uicollectionviewcompositionallayout uicollectionviewdiffabledatasource

10
推荐指数
0
解决办法
1324
查看次数

UICollectionViewDiffableDataSource 是否与 UICollectionViewDataSourcePrefetching 一起使用?

我的理解是 UICollectionViewDataSourcePrefetching 是为 UICollectionViewDataSource 构建的,而 UICollectionViewDiffableDataSource 似乎没有任何有关预取的文档。

uicollectionview swift uicollectionviewdiffabledatasource

8
推荐指数
1
解决办法
1284
查看次数

Swift:如何有选择地返回集合视图部分的标题?

我有一个UICollectionViewDiffableDataSource这样的:

var data:UICollectionViewDiffableDataSource<Section, Message>!
Run Code Online (Sandbox Code Playgroud)

我像这样定义节标题的布局:

let header = NSCollectionLayoutBoundarySupplementaryItem(
    layoutSize: .init(widthDimension: .fractionalWidth(1.0), heightDimension: .estimated(10)),
    elementKind: UICollectionView.elementKindSectionHeader,
    alignment: .top
)
section.boundarySupplementaryItems = [header]
Run Code Online (Sandbox Code Playgroud)

最后,为了返回我的标头,我有一个返回UICollectionReusableView类似以下内容的函数:

func setupHeaderData() {
    data.supplementaryViewProvider = { collectionView, kind, indexPath in
        return DateStampBuilder(data: self.data, style: self.style).build(collectionView: collectionView, kind: kind, indexPath: indexPath)
    }
}
Run Code Online (Sandbox Code Playgroud)

很棒的是:我可以在我的UICollectionView.

我想要什么:我如何可以选择不显示特定部分的特定标题?

当我尝试nil在以下函数中返回时:

data.supplementaryViewProvider = { collectionView, kind, indexPath in
Run Code Online (Sandbox Code Playgroud)

我收到以下错误:

Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'the view returned from -collectionView:viewForSupplementaryElementOfKind:atIndexPath …
Run Code Online (Sandbox Code Playgroud)

ios uicollectionview swift uicollectionviewcompositionallayout uicollectionviewdiffabledatasource

7
推荐指数
1
解决办法
5464
查看次数

UICollectionViewCompositionalLayout 可选部分

我看过这个问题,它是类似的:How to deal with empty items section in UICollectionView CompositionalLayout,但答案似乎是在快照中留下部分(我这样做,但这留下了另一个问题,我描述了这个问题)稍后)或渲染一个非常小的部分。该解决方案似乎不是一个好的解决方案。


我有一个集合视图,使用具有可比较数据源的组合布局。集合视图有四个部分,但每个部分都是可选的,这意味着如果该部分的相应数据为空,则不应显示该部分。

代码

布局定义

我有一个部分提供程序,它使用sectionIndex来配置每个部分的外观。我认为这很糟糕,因为例如,如果我在快照中没有第三部分的数据,那么通常应该在第四部分中的所有内容现在都会有一个索引路径,这将导致它像第三部分一样布局。

每个部分都有不同的项目大小,有些是正交滚动部分。因此,如果使用第三部分布局呈现第四部分数据,那么它看起来会是错误的。

NSCollectionLayoutSection * _Nullable (^sectionProvider)(NSInteger, id<NSCollectionLayoutEnvironment> _Nonnull) = ^NSCollectionLayoutSection * _Nullable (NSInteger sectionIndex, id<NSCollectionLayoutEnvironment> _Nonnull layoutEnvironment) {
    if (sectionIndex == 0) {
        //configure and return a layout for the first section
    } else if (sectionIndex == 1) {
        //configure and return a layout for the second section
    } else if (sectionIndex == 2) {
        //configure and return a layout for the third …
Run Code Online (Sandbox Code Playgroud)

ios uicollectionview nsdiffabledatasourcesnapshot uicollectionviewcompositionallayout uicollectionviewdiffabledatasource

7
推荐指数
1
解决办法
1859
查看次数

UICollectionViewDiffableDataSource - 具有不同散列的相同项目时崩溃

我用来UICollectionViewDiffableDataSource填充UICollectionView数据。我的理解是,DiffableDataSource通过使用来比较项目==,然后如果项目相等,它会比较hash值以查看是否发生了变化。

但根据我得到的错误,情况并非如此。

Diffable data source detected item identifiers that are equal but have different hash values. Two identifiers which compare as equal must return the same hash value. You must fix this in the Hashable (Swift) or hash property (Objective-C) implementation for the type of these identifiers
Run Code Online (Sandbox Code Playgroud)

就我而言,我有与 uniqueID 进行比较的项目,并且 hashValue 由用户输入的值确定。如果 == 和 hashValue 不能不同,那么使用它们有什么意义呢?

uikit uicollectionview swift uicollectionviewdiffabledatasource

7
推荐指数
1
解决办法
465
查看次数

UICollectionViewDiffableDataSource cellProvider 比预期更频繁地调用

我正在使用 UICollectionViewDiffableDataSource 来填充我的 UICollectionView。通过 REST API 收到项目列表后,我创建了一个新快照并像这样应用它:

DispatchQueue.main.async {
   var snapshot = NSDiffableDataSourceSnapshot<RegionSection, DiffableModel>()
   snapshot.appendSections(RegionSection.allCases)
   snapshot.appendItems(self.spotlights, toSection: .Spotlights)
   snapshot.appendItems(self.vendors, toSection: .Vendors)
   self.dataSource?.apply(snapshot, animatingDifferences: animated)
}
Run Code Online (Sandbox Code Playgroud)

在 cellProvider 中设置我的单元格时,我从 URL 异步加载图像。我注意到,第一个单元格会疯狂地浏览所有加载的图像,并最终显示与预期不同的图像。(例如,要由最后一个单元格显示的图像)。

我决定调查并发现cellProvider 闭包的调用次数是预期的两倍。此外, collectionView.dequeueReusableCell 函数在调用的前半部分表现得很奇怪,因为它每次都返回相同的单元格,即使 collectionView 中没有可以出队的单元格。

我的 cellProvider 关闭:

dataSource = UICollectionViewDiffableDataSource(collectionView: collectionView) { (collectionView, indexPath, entry) -> UICollectionViewCell? in
    if let spotlight = entry as? Spotlight{
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "spotlightCell", for: indexPath) as! SpotlightCell
        
        cell.nameLabel.text = spotlight.title
        cell.subtitleLabel.text = spotlight.subtitle
        cell.categoryLabel.text = spotlight.type.getDescription().uppercased()
        cell.imageView.loadImage(fromUrl: spotlight.titlePictureUrl)
                    
        return …
Run Code Online (Sandbox Code Playgroud)

uikit uicollectionview uicollectionviewcell swift uicollectionviewdiffabledatasource

5
推荐指数
1
解决办法
293
查看次数

如何将 UICollectionViewDiffableDataSource reorderHandlers 与自定义组合布局一起使用?

从 iOS 14 开始,UICollectionViewDiffableDataSource 有一个reorderHandlers属性。它在一些示例代码中进行了演示,并在WWDC 2020关于可比较数据源的进展的会议中进行了讨论。演示者指出您必须提供一个canReorderdidReorder闭包才能启用该功能。

示例代码在具有列表布局配置的集合视图中使用它,并使用重新排序附件配置列表单元格。和canReorder方法didReorder按预期调用。但是,如果我从单元中删除重新排序配件,重新排序将不再起作用 - 它不会调用任何一个关闭。它在我的应用程序中也不起作用,我在应用程序中有一个使用组合布局的网格布局。

如何在UICollectionViewDiffableDataSource没有列表单元的情况下启用重新排序并重新排序配件?

ios uicollectionview uicollectionviewdiffabledatasource

5
推荐指数
1
解决办法
510
查看次数

Diffable 数据源 - 重新加载标头

可以通过哪些方式UICollectionViewDiffableDataSource重新加载标头?

我有一个集合视图,其中的标题显示用户详细信息,行显示帖子,模型是

struct PostUser {
    var user: User
    var post: Post
}
Run Code Online (Sandbox Code Playgroud)

当我通过快照更改属性时

    var postUsers = [PostUser]() {
        didSet {
            self.applySnapshot(postUsers)
        }
    }

    fileprivate func applySnapshot(_ postsUser: [PostUser]) {
        var snapshot = NSDiffableDataSourceSnapshot<Section, PostUser>()
        snapshot.appendSections([.main])
        snapshot.appendItems(postsUser)
        self.datasource.apply(snapshot, animatingDifferences: true)
    }
Run Code Online (Sandbox Code Playgroud)

行会重新加载,但补充标题不会重新加载。我可以更改标题的唯一方法是使“部分”成为模型的一部分,因此:

    struct Section: Hashable {
        var User: User
    }
Run Code Online (Sandbox Code Playgroud)

我的应用快照现在变成

    fileprivate func applySnapshot(_ postsUser: [PostUser]) {
        var snapshot = NSDiffableDataSourceSnapshot<Section, PostUser>()
        snapshot.appendSections([Section(User: self.user)])
        snapshot.appendItems(postsUser)
        self.datasource.apply(snapshot, animatingDifferences: true)
    }
Run Code Online (Sandbox Code Playgroud)

然后我单独设置用户

    var user: User! = nil {
        didSet {
            self.applySnapshot(self.postUsers) …
Run Code Online (Sandbox Code Playgroud)

ios swift diffabledatasource uicollectionviewdiffabledatasource

4
推荐指数
1
解决办法
2579
查看次数

如何在不同的数据源中使用多个数据模型?

目前,我在尝试在应用程序中开发搜索视图时遇到了困难。我尝试将集合视图放置在表视图单元格中,并使用传统的集合视图数据源委托(行的单元格等),但是这些实现在现代应用程序中似乎都远非最佳。我们的应用程序使用“朋友”、“用户”和“场所”三个模型。

我们已经成功使用 Diffable 数据源和组合布局将其中一个模型填充到搜索视图中,但是当我尝试添加其他模型时,出现以下错误:

""*** 由于未捕获的异常“NSInternalInconsistencyException”而终止应用程序,原因:“无效参数不满足:部分!= NSNotFound”因未捕获的 NSException 类型异常而终止""

这是 SearchViewController

import UIKit

fileprivate typealias DataSource  = UICollectionViewDiffableDataSource<Section, SearchV2VC.DataType>
fileprivate typealias SourceSnapshot = NSDiffableDataSourceSnapshot<Section, SearchV2VC.DataType>

class SearchV2VC: UIViewController {
    
    
    var collectionView: UICollectionView! = nil
    private var dataSource: DataSource!
    var friendData = [FollowingInfo]()
    var userData = [FriendInfo]()
    var venueData = [Venue]()
   
    override func viewDidLoad() {
        super.viewDidLoad()
        
        configureHierarchy()
        configureDataSource()
        
        
    }
   
    private func firstLayoutSection() -> NSCollectionLayoutSection {

        let itemSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1), heightDimension: .fractionalHeight(0.5))

        let item = NSCollectionLayoutItem(layoutSize: itemSize)
        item.contentInsets.bottom = 15

        let …
Run Code Online (Sandbox Code Playgroud)

ios uicollectionview uicollectionviewdiffabledatasource

4
推荐指数
1
解决办法
6215
查看次数

为什么 UICollectionViewDiffableDataSource 在没有任何变化的情况下重新加载每个单元格?

我创建了以下演示视图控制器以在最小示例中重现该问题。

在这里,我使用 UICollectionViewDiffableDataSource 将相同数据的快照重复应用于相同的集合视图,并且每次重新加载所有单元格时,即使没有任何更改。

我想知道这是否是一个错误,或者我是否“持有错误”。

看起来这个其他用户也有同样的问题,尽管他们没有提供足够的信息来准确地重现错误: iOS UICollectionViewDiffableDataSource 重新加载所有数据而不做任何更改

编辑:我还发现了一个奇怪的行为 - 如果动画差异是true,则不会每次都重新加载单元格。

import UIKit

enum Section {
    case all
}

struct Item: Hashable {
    var name: String = ""
    var price: Double = 0.0

    init(name: String, price: Double) {
        self.name = name
        self.price = price
    }
}


class ViewController: UIViewController {
    private let reuseIdentifier = "ItemCell"
    private let collectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout())
    private lazy var dataSource = self.configureDataSource()

    private var items: [Item] = [ …
Run Code Online (Sandbox Code Playgroud)

ios uicollectionview uicollectionviewdiffabledatasource

3
推荐指数
1
解决办法
103
查看次数