为什么两个表视图单元格中的两个集合视图不能在swift 4中工作?

时间:2017-11-28 11:52:41

标签: swift uitableview uicollectionview uicollectionviewcell swift4

我读过类似的问题,例如如何在多个表视图单元格中拥有多个集合视图,并且我连接了我的集合视图单元格并使用了标识符名称,但我不知道为什么会收到此错误:

*由于未捕获的异常终止应用程序' NSInternalInconsistencyException',原因:'无法使类型的视图出列:具有标识符extera_infoCollectionViewCell的UICollectionElementKindCell - 必须注册一个nib或类标识符或连接故事板中的原型单元格' * 首先抛出调用堆栈:

**请记住,我读过类似的问题,第一个表视图单元格,集合视图运行良好,问题是第二个** 这是我的主视图控制器的代码,它有一个表视图,表视图有两个单元格

func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {

    if collectionView == fieldOfActivityCell().fieldofActivitiesCollectionView {
    let fullfields : String = self.adv.resultValue[0].work_field!
    let fullfieldsArr : [String] = fullfields.components(separatedBy: ",")
    print(fullfieldsArr)
    return fullfieldsArr.count

    } else {

            let extera_infofields : String = self.adv.resultValue[0].extera_info!
            let extera_infofieldsArr : [String] = extera_infofields.components(separatedBy: ",")
            print(extera_infofieldsArr)
            return extera_infofieldsArr.count



    }
}

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {


    if collectionView == fieldOfActivityCell().fieldofActivitiesCollectionView {

        let fieldsCells = collectionView.dequeueReusableCell(withReuseIdentifier: "fieldOfActivityCollectionViewCell", for: indexPath) as! fieldOfActivityCollectionViewCell



    let fullfields : String = self.adv.resultValue[0].work_field!
    let fullfieldsArr : [String] = fullfields.components(separatedBy: ",")

    fieldsCells.title.text = fullfieldsArr[indexPath.row]

    return fieldsCells

    }

    else {



        let extera_infoCells = collectionView.dequeueReusableCell(withReuseIdentifier: "extera_infoCollectionViewCell", for: indexPath) as! extera_infoCollectionViewCell



        let extera_info : String = self.adv.resultValue[0].extera_info!
        let extera_infoArr : [String] = extera_info.components(separatedBy: ",")

        extera_infoCells.infoText.text = extera_infoArr[indexPath.row]

        return extera_infoCells





    }

    }

,这是同一视图控制器中的表视图代码

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {


if indexPath.row == 0{

        let fieldCell = self.showAdvTableView.dequeueReusableCell(withIdentifier: "fieldOfActivityCell", for: indexPath) as! fieldOfActivityCell



        return fieldCell

} else {

  let fieldCell = self.showAdvTableView.dequeueReusableCell(withIdentifier: "extera_infoCell", for: indexPath) as! extera_infoCell

            return fieldCell

}

这是表格视图第一个单元格类

class fieldOfActivityCell: UITableViewCell {

@IBOutlet weak var fieldofActivitiesCollectionView: UICollectionView!

override func awakeFromNib() {
    super.awakeFromNib()
    // Initialization code

    if let flowLayout = fieldofActivitiesCollectionView.collectionViewLayout as? UICollectionViewFlowLayout { flowLayout.estimatedItemSize = CGSize.init(width: 1.0, height: 1.0) }
}

override func setSelected(_ selected: Bool, animated: Bool) {
    super.setSelected(selected, animated: animated)

    // Configure the view for the selected state
}

}

extension fieldOfActivityCell {

func setCollectionViewDataSourceDelegate
            <D: UICollectionViewDelegate & UICollectionViewDataSource>
    (_ dataSourceDelegate:D , forRow row : Int )

{

    fieldofActivitiesCollectionView.delegate = dataSourceDelegate
    fieldofActivitiesCollectionView.dataSource = dataSourceDelegate
    fieldofActivitiesCollectionView.reloadData()
}




}

这是第二个tableview单元类

 @IBOutlet weak var extra_infoCollectionView: UICollectionView!

override func awakeFromNib() {
    super.awakeFromNib()

    if let flowLayout = extra_infoCollectionView.collectionViewLayout as? UICollectionViewFlowLayout { flowLayout.estimatedItemSize = CGSize.init(width: 1.0, height: 1.0) }
}

override func setSelected(_ selected: Bool, animated: Bool) {
    super.setSelected(selected, animated: animated)

    // Configure the view for the selected state
}

}

 extension extera_infoCell {

func setCollectionViewDataSourceDelegate
    <D: UICollectionViewDelegate & UICollectionViewDataSource>
    (_ dataSourceDelegate:D , forRow row : Int )

{

    extra_infoCollectionView.delegate = dataSourceDelegate
    extra_infoCollectionView.dataSource = dataSourceDelegate

    extra_infoCollectionView.reloadData()
}




  }

enter image description here

3 个答案:

答案 0 :(得分:1)

答案是使用标签我只需要为它们使用标签,并使用if else选择哪个集合视图选择了标签,所以答案是这样的:

if collectionView.tag == 49 {
do some thing//////
}else {
do some thing else}

我应该在cellForRowAtIndexPath和numberOfRows方法中使用它,你也可以将它用于表视图

答案 1 :(得分:0)

根据您的错误,您的重用标识符与故事板中的任何单元格都不匹配。单击界面构建器中的extera_info collectionView单元格。选择属性检查器选项卡。在重用标识符下,确保您输入 extera_infoCollectionViewCell

答案 2 :(得分:-1)

上面的Saeed的标签选项可能是最简单的答案,但是发现他的描述有点简短,因此,对于以前从未使用过标签的人,下面添加一个更完整的答案...

如果遵守MVC并将collectionView dataSource方法放置在UITableView类内(而不是UITableViewCell类内),并且希望避免出现此错误:

您使用的每个集合视图将需要其自己的dequeueReusableCell标识符:

  1. 在interface-builder中,为集合视图单元格命名所有标识符。例如CatPicCell和DogPicCell。
  2. 在CellForItemAt collectionView方法中,设置if语句或switch语句,以便将每个重用标识符设置为等于您在interface-builder中创建的标识符(步骤1)。如果使用开关/案例,则可以将您的值设置为collectionView.tag。标签可以编号以标识每个不同的collectionView。标签就像将您的collectionViews集转换成字典或数组一样,以便每个collectionView都有自己的唯一键/索引。
  3. 返回interface-builder,进入情节提要,然后选择每个集合视图(每个视图应在其自己的tableView单元内)。在Xcode的“属性检查器”中,向下滚动到“视图”部分,向下滚动3个空格(Xcode 11,Swift 5),您将看到一个名为“ Tag”的字段。为该集合视图分配一个整数值,然后对将要嵌入到UITableView单元格中的每个集合视图重复此过程。
  4. 一旦所有的集合视图都标有唯一的整数,您只需将案例设置为整数,并为每个dequeueReusableCell标识符赋予与情节提要中相同的整数索引。

现在,当您在TableViewCell类中退出的collectionView上使用tableView单元格调用时,它将能够获取适当的dequeueReusable ID。您可以将数据放入每个开关盒中。

Voila,您现在具有一组需要方法的collectionView数据源,但可以提供所有的collection视图。甚至更好,当有人扩展项目并添加另一个collectionView时,就像在情节提要中向开关和标识符添加另一个案例一样容易。

示例代码如下:

        // I need a switch statement which will set the correct (of the 3 collectionViews) dequeueReusable IDENTIFIER for the collectionView
    switch collectionView.tag {
        //if tableView is doing cell == 1, then "CatsCell"
        //if ...                cell == 3, then "DogsCell"
        //if ...                cell == 5, then "BirdsCell"
    case 1:
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CatsCell", for: indexPath) as! CatsCVCell
        // put your required data here
        return cell
    case 3:
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "DogCell", for: indexPath) as! DogsCVCell
        // example data
        let dogs = dogController.fetch()
        cell.name = dogs[indexPath.item].dogName
        if let image = UIImage(data: groups[indexPath.item].image!) {

            cell.image = image
        }
        return cell
    case 5:
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "BirdCell", for: indexPath) as! BirdCVCell
        // put data code here for birds collection view cells
        return cell
    default:
        return UICollectionViewCell()  // or write a fatalError()
    }

注意:对于switch语句的默认设置,您有两个选择... 1.像上面一样,一个通用但空的单元格实例 2.抛出错误。错误永远不会让您丢下所有情况,但是如果其他人改进您的代码并添加另一个collectionView但忘记添加切换用例,则可能会发生错误-因此使您的错误语句准确地解释问题所在。 / p>