2

我有一个问题NSDiffableDataSource。我创建了这个基本示例,其中包含一个UICollectionView显示随机数的单个项目:

import UIKit

class ViewController: UIViewController {

    enum Section {
        case main
    }
    
    enum Item {
        case myItem
    }
    
    var collectionView: UICollectionView!
    var dataSource: UICollectionViewDiffableDataSource<Section, Item>!
    
    lazy var myCellRegistration = UICollectionView.CellRegistration<UICollectionViewListCell, Void> { (cell, indexPath, _) in
        print("Cell registration called")
        var content = cell.defaultContentConfiguration()
        content.text = "\(Int.random(in: 0...10000))"
        cell.contentConfiguration = content
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        var config = UICollectionLayoutListConfiguration(appearance: .insetGrouped)
        
        let layout = UICollectionViewCompositionalLayout.list(using: config)
        collectionView = UICollectionView(frame: view.bounds, collectionViewLayout: layout)
        collectionView.translatesAutoresizingMaskIntoConstraints = false
        collectionView.backgroundColor = .systemGroupedBackground
        
        view.addSubview(collectionView)
        
        NSLayoutConstraint.activate([
            collectionView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
            collectionView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
            collectionView.topAnchor.constraint(equalTo: view.topAnchor),
            collectionView.bottomAnchor.constraint(equalTo: view.bottomAnchor)
        ])
        
        dataSource = UICollectionViewDiffableDataSource<Section, Item>(collectionView: collectionView, cellProvider: { [unowned self] (collectionView, indexPath, item) -> UICollectionViewCell? in
            
            switch item {
            case .myItem:
                return collectionView.dequeueConfiguredReusableCell(using: myCellRegistration, for: indexPath, item: ())
            }
        })
        
        DispatchQueue.global(qos: .background).async {
            while true {
                sleep(2)
                DispatchQueue.main.async {
                    var snapshot = NSDiffableDataSourceSnapshot<Section, Item>()
                    snapshot.appendSections([.main])
                    snapshot.appendItems([.myItem])
                    self.dataSource.apply(snapshot, animatingDifferences: true)
                }
            }
        }
        
    }
}

每 2 秒,我将相同的快照重新应用到数据源。由于快照没有改变,我希望单元格也不会更新。就是这样……有点。从视觉上看,单元格没有变化(显示的数字保持不变)。但是,每次快照更新时,数据源实际上都会调用单元注册闭包,因此单元的内容配置确实会发生变化。它只是没有被绘制。

有人知道这里发生了什么吗?

提供一点背景知识:我问这个的原因是我想Combine publisher在创建单元格的内容配置时订阅一个。然后发布者发布单元格的数据,单元格可以更新其视图,允许自定义动画。(我可以简单地将数据放入 中item identifier,但是任何数据更改只会导致单元格交叉淡入到新的单元格中。这不好)。

它看起来像这样:

// Event.Cell is some custom cell with a custom content configuration
lazy var myCellRegistration = UICollectionView.CellRegistration<Event.Cell, Void> { [unowned self] (cell, indexPath, _) in
    var content = Event.ContentConfiguration()
    
    self.myEventPublisher.sink { event in
        content.event = event
        cell.contentConfiguration = content // Re-set the contentConfiguration
    }.store(in: &content.disposeBag) // store the subscriber in a dispose bag inside the content configuration
}

由于与发布者和订阅者一起工作可能很棘手(内存泄漏和其他东西),我需要知道如何在不引起任何问题的情况下做到这一点,并且快照的行为很奇怪。至少在我看来是这样的

4

0 回答 0