如何从 UICollectionView.CellRegistration 访问更新的数据源

Posted

技术标签:

【中文标题】如何从 UICollectionView.CellRegistration 访问更新的数据源【英文标题】:How to access the updated datasource from the UICollectionView.CellRegistration 【发布时间】:2022-01-04 08:32:09 【问题描述】:

我想知道为什么数据源的值会更新,但是当我从单元格注册访问单个值时,值没有改变。 下面的代码就是我的意思。

我有一个名为 Event 的结构体,它接受三个值,id、name 和 streamState

struct Event: Codable, Hashable 
    let id: String
    let name: String
    let streamState: String


struct Events: Codable 
    let streams: [Event]

在我的 EventDataSource 类中,我有一个事件数组和用于从后端获取事件数据的 fetchEvent 函数,为了简单起见,我只添加了 1 个数据(1 个事件),所以我知道事件数组只有现在有一个数据。

class EventDataSource 
    var events = [Event]()

    func fetchEvents(completion: @escaping () -> Void) 
            AF.request(myEndpoint)
            .validate()
                .responseJSON  response in
                    
                    guard let data = response.data else  return 
                    let decoder: JSONDecoder = JSONDecoder()
                    var result: Events?
                    
                    do 
                        result = try decoder.decode(Events.self, from: data)
                     catch 
                        print("error with fetch events: \(error)")
                    
                    
                    guard let final = result else  return       
                    self.events = final.streams

                    if events.count > 0 
                        print("fetched first item: \(self.events[0].streamState), \(events[0].name)") // -> get the updated streamState with correct name
                    
                    
                    DispatchQueue.main.async 
                        completion()
                    
            
    

在上面的代码中,我添加了 if 语句 (events.count > 0) 以确保更新事件的 streamState。 (更具体地说,事件的streamState从init开始,但几秒钟后,它变成ready,我得到ready被打印出来,所以我想我可以说streamState在后端。)

我使用 CollectionViewListCell 显示事件数据,每当我使用 EventDataSource 中的 fetchEvents 函数更新事件数据时,我都会调用 displayEvents 函数来更新 collectionViewListCell。然后由于重新创建了单元格,因此也调用了 cellRegistration 部分。我打印了 event.streamState 中的内容,但它给了我原始值 (init),即使 fetchEvents 函数中获取的数据清楚地给了我更新后的值 (ready)。

class ListViewController: UIViewController, UICollectionViewDelegate 
    private var collectionViewDataSource: UICollectionViewDiffableDataSource<Section, Event>?
    private var snapshot: NSDiffableDataSourceSnapshot<Section, Event>!
    private var eventDataSource = EventDataSource()



    override func viewDidLoad() 
        displayEvents()
        configureDataSource()

    

    func displayEvents() 
        snapshot = NSDiffableDataSourceSnapshot<Section, Event>()
        snapshot.appendSections([.list])
        snapshot.appendItems(eventDataSource.Events)
        collectionViewDataSource?.apply(snapshot, animatingDifferences: false)
        collectionView.reloadData()
    

    func configureDataSource() 
        let cellRegistration = UICollectionView.CellRegistration<CustomListCell, Event>  cell, indexPath, event in
        print(event.streamState) // -> this value is not changed, only gives me the original value
        cell.event = event
    

    collectionViewDataSource = UICollectionViewDiffableDataSource<Section, Event (collectionView: collectionView)  (collectionView, indexPath, event) -> UICollectionViewCell? in
        let cell = collectionView.dequeueConfiguredReusableCell(using: cellRegistration, for: indexPath, item: event)
        return cell
    

我查了一些其他文章并用谷歌搜索,但我仍然不知道为什么会打印更新的值。我现在感觉卡住了,这就是我发布这个问题的原因。如果有人能指出我正确的方向,请告诉我...

【问题讨论】:

【参考方案1】:

在您的viewDidLoad() 实现中颠倒对configureDataSource()displayEvents() 的调用顺序,否则您将快照应用到nil 数据源。 另外,您将collectionViewDataSource 设置在configureDataSource() 的范围之外

【讨论】:

以上是关于如何从 UICollectionView.CellRegistration 访问更新的数据源的主要内容,如果未能解决你的问题,请参考以下文章

获取按钮操作:UICollectionView Cell

UICollectionView Cell Spacing 基于设备屏幕大小

保持 UICollectionView Cell 的值

ios . -- UICollectionView --cell 自适应

UICollectionView cell间距调整以及常用代理方法

UICollectionView Cell 在选择时不会改变