标签: nsdiffabledatasourcesnapshot

NSDiffableDataSourceSnapshot `reloadItems` 有什么用?

我很难找到 NSDiffableDataSourceSnapshot 的使用reloadItems(_:)

  • 如果我要求重新加载的项目不等于数据源中已经存在的项目,我就会崩溃。

  • 但是,如果该项目equatable到已存在的数据源中的项目,那么什么是“重装”,它的意义呢?

您可能认为第二点的答案是:嗯,项目标识符对象的其他方面可能不属于其等式性的一部分,但确实反映到单元格界面中。但我发现这不是真的。打完电话后reloadItems,表视图并没有反映这一变化。

因此,当我想更改一个项目时,我最终对快照所做的是insert在要替换的项目之后,然后是delete原始项目的一个。没有快照replace方法,这正是我希望的reloadItems结果。

(我对这些术语进行了 Stack Overflow 搜索,但发现的很少——主要是几个对 的特定用途感到困惑的问题reloadItems,例如如何使用 diffable UITableView 更新表格单元格。所以我以更通用的形式提问有人发现这种方法有什么实际用途?)


好吧,没有什么比拥有一个最小的可重现示例更合适的了,所以这里是一个。

使用其模板 ViewController 制作一个普通的香草 iOS 项目,并将此代码添加到 ViewController。

我会一块一块地拿走。首先,我们有一个结构体作为我们的项目标识符。UUID 是唯一的部分,因此等价性和哈希性仅取决于它:

struct UniBool : Hashable {
    let uuid : UUID
    var bool : Bool
    // equatability and hashability agree, only the UUID matters
    func hash(into hasher: inout Hasher) {
        hasher.combine(uuid)
    }
    static func …
Run Code Online (Sandbox Code Playgroud)

ios swift nsdiffabledatasourcesnapshot

24
推荐指数
4
解决办法
3290
查看次数

如何在不删除和插入 UITableViewDiffableDataSource 的情况下重新加载项目?

我正在我的应用程序中使用UITableViewDiffableDataSource. 每个单元格代表一个搜索命中并在单元格标题中突出显示搜索匹配项,有点像 Xcode 的 Open Quickly 窗口突出显示其结果项的部分。在搜索字段中输入文本时,我更新了结果列表。结果随着相关性的变化在列表中上下移动。

诀窍是每次搜索文本更改时我都需要强制每个单元格重新呈现,因为新的搜索字符串意味着更新单元格标题的突出显示部分。但我不想动画删除和插入,因为它仍然是同一个项目。如何使用快照告诉数据源它需要重新加载单元格?

我这样声明数据源:

@property (retain) UITableViewDiffableDataSource<NSString *, SearchHit *> *dataSource;
Run Code Online (Sandbox Code Playgroud)

SearchHit代表一个搜索结果;它具有显示标题和要在标题中突出显示的范围数组的属性。并且它会覆盖hashandisEqual:以便唯一标识每个结果行。

我的代码看起来像这样:

-(void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText
{
  NSArray<SearchHit *> *hits = [self fetchHits:searchText];
  NSDiffableDataSourceSnapshot<NSString *, SearchHit *> *snap = [[[NSDiffableDataSourceSnapshot alloc] init] autorelease];
  [snap appendSectionsWithIdentifiers:@[@""]];
  [snap appendItemsWithIdentifiers:hits];
  [snap reloadItemsWithIdentifiers:hits];
  [self.dataSource applySnapshot:snap animatingDifferences:YES];
}
Run Code Online (Sandbox Code Playgroud)

起初我没有在reloadItemsWithIdentifiers那里打电话,然后一旦它出现在结果列表中,任何单元格都不会改变。添加reload呼叫有帮助,但现在大多数单元格总是落后于一个更新。这在我的代码中的某处闻起来像是逻辑错误,但我已经验证传递给快照的命中是正确的,而传递给数据源的单元格创建回调的命中不是。

Donny Wals 的这篇文章和涉及 Steve Breen 的相关 Twitter 线程建议解决此问题的方法是使项目标识符类型仅表示显示单元格所需的属性。所以我更新了SearchHit的散列和相等比较以包含标题的突出显示部分,而他们以前没有。然后我在每次更新时删除并插入所有单元格的动画,这是我不想要的。

这看起来reloadItemsWithIdentifiers应该怎么做……对吧?

示例项目在这里 …

objective-c uitableview diffabledatasource nsdiffabledatasourcesnapshot

11
推荐指数
2
解决办法
2602
查看次数

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

我有一个集合视图(使用组合布局和可比较数据源),其标题中有一个分段控件。当控制值发生变化时,单元格会更新为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
查看次数

iOS13 DiffableDataSource 无效参数不满足:indexPath || 忽略无效项目

我正在将我的集合视图转换为新的 iOS13 UICollectionViewDiffableDataSource ......所以我需要根据需要更新单元格信息。

这是我的代码:

let snap = self.diffDataSouce.snapshot
snap?.reloadItems(withIdentifiers: [itemToUpdate]) //reload cell info
self.diffDataSouce.apply(snap, animatingDifferences: true)
Run Code Online (Sandbox Code Playgroud)

但我明白了Invalid parameter not satisfying: indexPath || ignoreInvalidItems……为什么?我的当前snap包含itemToUpdate以及我的模型数组...

我认为这是因为snap.indexOfItemIdentifier(itemToUpdate)未找到返回值(NSNotFound)……但根据数据模型,这应该是不可能的。

你有什么提示吗?

ios ios13 diffabledatasource nsdiffabledatasourcesnapshot

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

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
查看次数

UICollectionViewCompositionalLayout 的粘性标题不稳定

我正在尝试使用最新的 UICollectionViewCompositionalLayout 使用 UICollectionViewDiffableDataSource 显示分页数据。我想在该部分上方显示一个粘性标题,即使在从网络加载下一页数据时,该标题也始终保留在顶部。我注意到粘性标题没有按预期工作,而是在后台下载数据时感觉不稳定并应用新的快照..我能够使用苹果在此处共享的示例应用程序重现此问题

这是重现该问题的代码:

func layout() -> 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: .absolute(44))
    let group = NSCollectionLayoutGroup.horizontal(layoutSize: groupSize, subitems: [item])

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

    let sectionHeader = NSCollectionLayoutBoundarySupplementaryItem(
        layoutSize: NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0),
                                          heightDimension: .estimated(44)),
        elementKind: sectionHeaderElementKind,
        alignment: .top)
    sectionHeader.pinToVisibleBounds = true
    sectionHeader.zIndex = 2
    section.boundarySupplementaryItems = [sectionHeader]

    let layout …
Run Code Online (Sandbox Code Playgroud)

swift ios13 nsdiffabledatasourcesnapshot uicollectionviewcompositionallayout

6
推荐指数
0
解决办法
1714
查看次数

iOS UICollectionViewDiffableDataSource 重新加载所有数据,没有任何更改

我有一个简单的UICollectionView1 个部分和 1 个项目类型,由新的 iOS 13 提供支持UICollectionViewDiffableDataSource

即使没有更改数据源(相同hashValue),UICollectionViewDiffableDataSource也会更新整个集合视图(调用cellProvier每个可见单元格)。

问题是,相同的场景按UITableViewDiffableDataSource预期工作,即不更改数据源,UITableViewDiffableDataSource 什么也不做

这是设计上的差异,还是某种错误?

uikit ios ios13 diffabledatasource nsdiffabledatasourcesnapshot

6
推荐指数
0
解决办法
324
查看次数

Diffable 快照重新加载节标题

当使用 重新加载表视图数据时NSDiffableDataSourceSnapshot,表视图将仅重新加载包含与先前快照的差异的部分。

我有一个表视图,其中包含具有特定日期的条目。根据用户在分段控件中选择的内容,条目按条目周/月/自定义日期范围的部分进行排序。

当我有一个周部分并且本周是本月唯一存在的一周时,当用户选择不同的日期范围时该部分将不会更新,并且标题将保持不变。

无论此快照与上一个快照之间是否存在差异,如何才能重新加载所有节标题?

这是设置快照的代码:

struct EntriesSection {

    let date: Date
    var entries: [Entry] = []
}

var sections: [EntriesSection]()

private func setupSnapshot() {

    snapshot = NSDiffableDataSourceSnapshot<Date, Entry>()

    sections.forEach {
        snapshot.appendSections([$0.date])
        snapshot.appendItems($0.entries, toSection: $0.date)
    }

    dataSource?.apply(snapshot, animatingDifferences: true)
}
Run Code Online (Sandbox Code Playgroud)

结果:

提前致谢。

iphone uitableview ios swift nsdiffabledatasourcesnapshot

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

将 NSDiffableDataSourceSnapshot 应用于 UICollectionViewDiffableDataSource 会导致“NSInternalInconsistencyException”

我正在尝试UICollectionViewDiffableDataSource为我的collectionView. 我的代码编译得很好,但是我第一次对它应用快照时一直遇到这个错误,并出现以下错误:

由于未捕获的异常“NSInternalInconsistencyException”而终止应用程序,原因:“无效参数不满足:self.supplementaryViewProvider || (self.supplementaryReuseIdentifierProvider && self.supplementaryViewConfigurationHandler)'

这是我的代码:

    var groups: [Group] = [Group]()
    var dataSource: UICollectionViewDiffableDataSource<Section, Group>!

    // MARK: - View Life Cycle
    override func viewDidLoad() {
        super.viewDidLoad()

        self.searchBar.delegate = self
        self.groups = DummyData.groups

        setupDataSource()
    }

    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
        performSearch(searchQuery: nil)
    }


    // MARK: - Helper Functions
    func performSearch(searchQuery: String?) {
        let filteredGroups: [Group]
        if let searchQuery = searchQuery, !searchQuery.isEmpty {
            filteredGroups = groups.filter { $0.contains(query: searchQuery) }
        } else {
            filteredGroups = groups …
Run Code Online (Sandbox Code Playgroud)

uikit uicollectionview swift5 diffabledatasource nsdiffabledatasourcesnapshot

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

如何在 UITableViewDiffableDataSource 中添加标题名称

我尝试为 中的每个部分添加标题UITableView,但在这种情况下UITableViewDiffableDataSource,我不知道应该在哪里做。我的代码的一部分:

private func prepareTableView() {
    tableView.delegate = self
    tableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell")
    dataSource = UITableViewDiffableDataSource<Sections, User>(tableView: tableView, cellProvider: { (tableView, indexPath, user) -> UITableViewCell? in
        let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
        cell.textLabel?.text = user.name
        return cell
    })
}

private func addElement(_ user: User) {
    var snap = NSDiffableDataSourceSnapshot<Sections, User>()
    snap.appendSections([.main, .second])
    if isFirst {
        users.append(user)
    } else {
        secondUsers.append(user)
    }
    snap.appendItems(users, toSection: .main)
    snap.appendItems(secondUsers, toSection: .second)
    isFirst.toggle()
    dataSource.apply(snap, animatingDifferences: true, completion: nil)
    dataSource.defaultRowAnimation = .fade …
Run Code Online (Sandbox Code Playgroud)

uitableview swift diffabledatasource nsdiffabledatasourcesnapshot

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