子类化 UICollectionViewCell 并从 xib 初始化

Posted

技术标签:

【中文标题】子类化 UICollectionViewCell 并从 xib 初始化【英文标题】:Subclassing UICollectionViewCell and initialising from xib 【发布时间】:2015-06-19 07:50:12 【问题描述】:

我正在像这样注册单元格:

collectionView!.registerNib(UINib(nibName: "ItemCell", bundle: nil), forCellWithReuseIdentifier: "ItemCellIdentifier")

并像这样访问它:

let cell = collectionView.dequeueReusableCellWithReuseIdentifier("ItemCellIdentifier", forIndexPath: indexPath) as! ItemCell

ItemCell 是 UICollectionViewCell 的子类:

class ItemCell: UICollectionViewCell 

    @IBOutlet weak var itemImage: UIImageView!
    @IBOutlet weak var itemImageDescription: UILabel!

    //creation from nib requires this method to be overridden
    override func awakeFromNib() 
        super.awakeFromNib()
        // Initialization code
    

    required init(coder aDecoder: NSCoder) 
        super.init(coder: aDecoder)
    

最后我有一个带有类 ItemCell 的 UICollectionViewCell 的 xib。

我不断收到错误:

-[UICollectionView 中的断言失败 _dequeueReusableViewOfKind:withIdentifier:forIndexPath:viewCategory:], /SourceCache/UIKit/UIKit-3347.44.2/UICollectionView.m:3443.

崩溃就在这一行:

let cell = collectionView.dequeueReusableCellWithReuseIdentifier("ItemCellIdentifier", forIndexPath: indexPath) as! ItemCell

编辑

collectionView!.registerNib(UINib(nibName: "ItemCell", bundle: nil), forCellWithReuseIdentifier: "ItemCellIdentifier")

被调用

override init(style: UITableViewCellStyle, reuseIdentifier: String?) 
    super.init(style: style, reuseIdentifier: reuseIdentifier)


包含在:

class CollectionCell : UITableViewCell, UICollectionViewDataSource, UICollectionViewDelegate 

【问题讨论】:

【参考方案1】:

你在哪里打电话给registerNib

我复制了设置以匹配我从你那里得知的内容。

这对我有用,没有错误:

import UIKit

class ViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate 

    var model:[String] = []

    @IBOutlet weak var collectionView: UICollectionView!

    override func viewDidLoad() 
        super.viewDidLoad()

        // just a simple test model ...
        for index in 1...100 
            model.append("\(index)")
        

        // register the nib
        collectionView.registerNib(UINib(nibName: "ItemCell", bundle: nil), forCellWithReuseIdentifier: "ItemCell")

        // this is just a test layout
        var layout = UICollectionViewFlowLayout()
        layout.itemSize = CGSize(width:200.0,height:200.0)
        layout.scrollDirection = UICollectionViewScrollDirection.Vertical
        self.collectionView.collectionViewLayout = layout
        self.collectionView.delegate = self;
        self.collectionView.dataSource = self;
        self.collectionView.reloadData()
    

    // MARK: -  UICollectionViewDataSource
    func collectionView(collectionView: UICollectionView,
        numberOfItemsInSection section: Int) -> Int
            return model.count
    

    func collectionView(collectionView: UICollectionView,
        cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell
            var cell:UICollectionViewCell = collectionView.dequeueReusableCellWithReuseIdentifier("ItemCell", forIndexPath: indexPath) as! UICollectionViewCell
            return cell
    

【讨论】:

Alessandro,您的编辑说您正在从自定义 UITableViewCell 的初始化程序内部调用 registerNib ?对不起,这根本没有任何意义。 registerNib 应该在 viewDidLoadUIViewController 方法上调用。 它实际上是一个 UITableViewCell,里面有一个集合视图 UICollectionView 应该只显示 UICollectionViewCell 的。我建议阅读有关 UICollectionView 的文档,然后完全重新制定您的设置。你所做的事情没有什么意义,代码质量很差,难怪你会出错。 在您的示例中,您正在做同样的事情。您正在从 UIViewController 添加一个 collectionView。我从 UITableViewCell 中添加它 一个 UIViewController 是一个控制器。 UITableViewCell 是一个视图。在 MVC 范式中,这两件事非常不同,我无法解释这一点,请阅读 MVC 以了解差异。在任何情况下,很难从您显示的代码中说出来,但是如果您正在做的是在 UITableViewCell 中添加一个 UICollectionView 来满足一些复杂的布局需求,那么调用 registerNib 的正确位置是 UIViewController 中的 viewDidLoad 方法,它持有界面视图。单元格的 init() 方法根本无法正常工作(如果确实如此,也不应该尝试)。【参考方案2】:

尝试在主包中搜索

collectionView!.registerNib(UINib(nibName: "ItemCell", bundle: NSBundle.mainBundle()), forCellWithReuseIdentifier: "ItemCellIdentifier")

【讨论】:

【参考方案3】:

崩溃是因为向下转换失败。而不是使用强制形式作为!使用条件 as?

尝试其他方式来注册单元格:

ViewDidLoad

collectionView.registerClass(ItemCell.self,forCellWithReuseIdentifier:"ItemCellIdentifier")

cellForItemAtIndexPath

func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath:NSIndexPath)->UICollectionViewCell

      var  cell = collectionView.dequeueReusableCellWithReuseIdentifier("ItemCellIdentifier", forIndexPath: indexPath) as ItemCell
    cell.titleLabel.text="cellText"
    return cell

【讨论】:

编译器强制我使用 as!。它说“AnyObject”不能转换为“itemCell” 我已经编辑了我的答案。我的编译器没有强迫我使用 as! 为什么要覆盖 ItemCell 中的初始化程序?除了调用 super 之外,您实际上并没有在任何一个初始化程序中做任何事情,因此您不需要实现任何一个初始化程序!如果你不重写任何指定的初始化器,你继承你的超类的所有指定的初始化器。

以上是关于子类化 UICollectionViewCell 并从 xib 初始化的主要内容,如果未能解决你的问题,请参考以下文章

子类化从 xib 创建的自定义视图

无法在 xib 文件中选择 UICollectionViewCell

如何以不同的方法访问 uicollectionviewcell 对象?

UICollectionViewCell 子类问题

将子视图添加到 UICollectionViewCell 子类?

试图确定子类 UICollectionViewCell 中的单元格宽度