Swift collectionView 不可重用单元格

Posted

技术标签:

【中文标题】Swift collectionView 不可重用单元格【英文标题】:Swift collectionView non reusable cell 【发布时间】:2016-03-06 23:52:30 【问题描述】:

我有一个包含 2 个部分的 collectionView,每个部分都应基于同一个单元格(仅包含一个 UIImageView)。 这些部分之间的唯一区别是它们应包含的单元格数量和显示的图像类型。

如果我将 cellforItemAtIndexPath 方法设置为使用出队的单元格 (collectionView.dequeueReusableCellWithIdentifier),一切都会正常填充,如果我将其设置为使用自定义单元格的实例而不出队,则会崩溃。

cellForItemAtIndexPath 方法:

    func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell 
        //cannot use dequedReusableCell since some cells below scroll-line should remain highlighted
        let cell = NumbersCollectionViewCell() // CAUSES CRASH
//        let cell = collectionView.dequeueReusableCellWithReuseIdentifier(Constants.cellIdentifier, forIndexPath: indexPath) as! NumbersCollectionViewCell // WORKS FINE
        switch indexPath.section 
        case 0: cell.imageView.image = UIImage(named: numberImageFiles[indexPath.row])
        case 1: cell.imageView.image = UIImage(named: specialNumberImageFiles[indexPath.row])
        default: break
        
        return cell
    

NumbersCollectionViewCell 定义:

class NumbersCollectionViewCell: UICollectionViewCell 
    @IBOutlet weak var imageView: UIImageView!

出现的错误是:“致命错误:在展开可选值时意外发现 nil”,它突出显示了我的 cellForItemAtIndexPath 方法中的“case 0”行。

我不想使用出队单元格的原因是我需要在运行时根据用户选择突出显示一些单元格,如果我使用出队单元格,它似乎不会保留突出显示滚动线下方的那些。

【问题讨论】:

原来我的问题与单元格出队无关......这都在 didSelect 和 didDeselectCellAtIndexPath 方法中......但如果我的问题与单元格出队有关,下面的答案会有工作。 【参考方案1】:

假设您的单元格同时拥有.swift.xib 文件,您需要像这样实例化您的NumbersCollectionViewCell: 例如

let numbersCollectionViewCell = UINib(nibName: "NumbersCollectionViewCell", bundle: bundle).instantiateWithOwner(nil, options: nil)[0] as! NumbersCollectionViewCell

否则,您的IBOutlets 将无法连接。

【讨论】:

所以我最初没有 .xib,但我删除了 NumbersCollectionViewCell.swift 文件,这次用 .xib 重新创建了它。问题是,当我输入您建议的代码时,Xcode 会在该行上提供一条警告,指出“Cast from '[AnyObject]!'到不相关的类型'NumbersCollectionViewCell'总是失败“当我在模拟器上运行应用程序时,它会崩溃突出显示该行但在控制台中不提供任何消息【参考方案2】:
 override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell 
     guard let cell = collectionView.dequeueReusableCellWithReuseIdentifier(identifier: "NumbersCollectionViewCell">, forIndexPath: NSIndexPath>) as? NumbersCollectionViewCell else 
         print("failed to get cell")
         return UICollectionViewCell()
         
     switch indexPath.section 
         case 0: cell.imageView.image = UIImage(named: numberImageFiles[indexPath.row])
         case 1: cell.imageView.image = UIImage(named: specialNumberImageFiles[indexPath.row])
         default: break
         
   return cell

【讨论】:

不幸的是,使用建议的代码它仍在使单元格出队,这意味着滚动线下方的单元格不会显示为阴影。因此,如果我有一些在运行时被着色的单元格,然后用户向下滚动并向上滚动,则被着色的单元格现在不再被着色,因为这些单元格已出列并重新创建。

以上是关于Swift collectionView 不可重用单元格的主要内容,如果未能解决你的问题,请参考以下文章

如何强制刷新重用的 collectionview 单元格?

取消注册单元格以在 TableView/CollectionView 中重用有啥意义吗?

在 collectionView 中重用时不应用 UIImageView 大小

iOS 使用多个 CollectionView 重用同一个单元格

collectionView 分为三行 swift 4

Swift:按下collectionView项目时推送新视图