【问题标题】:Swift UITableView / UICollectionVIew passing data to cell in cellForRowAt returns nilSwift UITableView / UICollectionVIew 将数据传递到 cellForRowAt 中的单元格返回 nil
【发布时间】:2020-09-13 00:06:56
【问题描述】:

我正在尝试将结构从集合视图传递到 cellForRowAt 方法中的单元格。我也尝试过使用表格视图,但它产生了同样的错误。

集合视图类代码:

class PaintingListCollectionViewController: UICollectionViewController {
    
    var allPaintings: CategorySection!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        ...
    }
    
    // MARK: UICollectionViewDataSource
    override func numberOfSections(in collectionView: UICollectionView) -> Int {
        return 1
    }
    
    override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return allPaintings.paintings.count
    }
    
    override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "paintingCell", for: indexPath) as? PaintingCollectionViewCell
        
        // works perfectly
        cell?.paintingTitleLabel.text = allPaintings.paintings[indexPath.item].title
        cell?.paintingImageView.image = UIImage(named: allPaintings.paintings[indexPath.item].title)
        
        cell?.paintingData = allPaintings!.paintings[indexPath.item]

        // prints out two valid data
        print(cell?.paintingData, allPaintings!.paintings[indexPath.item])
    
        return cell!
    }

}

单元类代码:

class PaintingTableViewCell: UITableViewCell {
    @IBOutlet weak var paintingImageView: UIImageView!
    @IBOutlet weak var paintingNameLabel: UILabel!
    var paintingData: Painting?

    override func awakeFromNib() {
        super.awakeFromNib()

        // always returns nil, despite printing out the exact same thing in cellForItemAt returns a valid result. 
        print(paintingData)
    }

}

我正在使用以下结构:

struct CategorySection {
    var title: String
    var image: String
    var color: UIColor
    var paintings: [Painting]
}

struct Painting {
    var title: String
    var size: String
    var year: String
    var text: String
}

我发现,如果我将数据直接传递给单元格的 @IBOutlet UI 属性,它就可以工作。但是当我将数据传递给 UITableViewCell 类中的可选变量时,结果总是为零。如果我也使用 UITableView,就会出现这个问题。另外,我需要提一下,TableView 类中的var allPaintings: CategorySection! 也使用与此处描述的完全相同的方式从另一个表视图控制器传递。所以这里发生的数据传递已经是链上的第二次了。

这是一个非常奇怪的错误...如果有人可以帮助我,我将非常感谢!

已编辑:原始问题描述使用 UITable 视图而不是集合视图,以及数据源的节而不是行。我出于调试目的进行了这些更改。

【问题讨论】:

  • “paintingData”是什么样的?您是否有意为每个单元格加载相同的数据?为什么要使用 indexPath.section?
  • 我刚刚编辑了我的帖子以获取更多详细信息。我使用部分而不是行来进行样式设置。我认为传递数据时没有任何区别。
  • 将部分和行混淆在逻辑上是不正确的。您的数据源设置不正确。
  • 至于单元格,我会解开所有这些选项,从单元格开始,然后继续寻找为什么绘画始终为零。
  • 为了“更好的逻辑”,我切换到行而不是部分。 cellForRowAt 中的 print( cell?.paintingData, allPaintings!.paintings[indexPath.row]) 现在会生成两个有效数据,但在单元格类中打印 paintingData 仍然返回 nil。

标签: swift xcode uitableview


【解决方案1】:

如果您在 awakeFromNib 和 cellForRowAt 中的打印语句上设置断点,您将看到在将数据放入 collectionViewCell 之前调用了 awakeFromNib。事实上,它被collectionView.dequeueReusableCell() 调用。你想使用 UICollectionViewCell.didMoveToSuperview()

class PaintingCollectionViewCell: UICollectionViewCell {
    @IBOutlet weak var paintingImageView: UIImageView!
    @IBOutlet weak var paintingNameLabel: UILabel!
    var paintingData: Painting?
    
    override func awakeFromNib() {
        super.awakeFromNib()
        
        // always returns nil, despite printing out the exact same thing in cellForItemAt returns a valid result.
        print("Awake From Nib", paintingData)
    }
    
    override func didMoveToSuperview() {
        print ("did Move To Superview", paintingData)
    }
}

我添加了一个守卫来检查cellForRowAt,如果由于某种原因它无法创建单元格,函数的最后一行将崩溃 return cell!

override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "paintingCell", for: indexPath) as? PaintingCollectionViewCell else {
        fatalError("unable to dequeue cell")
    }
    
    // works perfectly
    cell.paintingNameLabel?.text = allPaintings.paintings[indexPath.item].title
    cell.paintingImageView.image = UIImage(named: allPaintings.paintings[indexPath.item].title)
    
    cell.paintingData = allPaintings!.paintings[indexPath.item]
    
    // prints out two valid data
    print("cellForItemAt ",cell.paintingData ?? "nothing to see here", allPaintings!.paintings[indexPath.item])
    
    return cell
}

【讨论】:

  • 使用行而不是部分将始终将数据的第一部分传递给单元格......这不是我想要的。尽管 cellForRowAt 中的 print(cell?.paintingData, allPaintings!.paintings[indexPath.section]) 现在打印了两个有效数据,但 awakeFromNib() 中的 print(paintingData) PaintingTableViewCell: UITableViewCell 中的 PaintingTableViewCell: UITableViewCell 仍然返回 nil...
  • 对。我的电线在那里交叉。您需要同时使用 indexPath.section 和 indexPath.row 在 allPaintings 中找到正确的项目。如果所有部分的行数相同,则可以使用realIndex = indexPath.section * numberOfItemsPerSection + indexPath.row 访问它们。然后参考allPaintings!.paintings[realIndex] 否则绘画需要是一个二维数组所以paintings[indexPath.section][indexPath.row] 返回你正在寻找的东西
  • 我切换到集合视图,并使用集合视图的等效行:'item''。而且这个bug依然存在。现在我有很多项目和 1 个部分。但是,cellForItemAt 中的 print(cell?.paintingData, allPaintings!.paintings[indexPath.row]) 现在会生成两个有效数据,但在单元格类中打印 paintingData 仍然返回 nil。有关详细信息,请参阅编辑后的问题描述。
  • 对于您使用indexPath.item 的集合视图,因此您应该将所有出现的indexPath.row 替换为indexPath.item
  • 对不起,我没有正确更新帖子。我正在使用项目。问题仍然存在。
猜你喜欢
  • 2021-11-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-04-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多