【问题标题】:Why two collection views in two table view cells won't work in Swift 4?为什么两个表格视图单元格中的两个集合视图在 Swift 4 中不起作用?
【发布时间】:2017-11-28 11:52:41
【问题描述】:

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

* 由于未捕获的异常“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) }
}
}

 extension extera_infoCell {

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

    {
        extra_infoCollectionView.delegate = dataSourceDelegate
        extra_infoCollectionView.dataSource = dataSourceDelegate
        extra_infoCollectionView.reloadData()
    }
}

【问题讨论】:

    标签: ios swift uitableview uicollectionview uicollectionviewcell


    【解决方案1】:

    第一步: 使用标签 - 你只需要为它们使用标签并使用 if else 来选择使用标签选择的集合视图,所以答案是这样的:

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

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

    第二步:您必须在 CollectionView 数据源的 cellForRowAt 方法中更改要出列的“集合视图”的名称:

    if collectionView.tag == 1 {
        let cell = yourFirstCollectionView.dequeueReusableCell(...) as yourCell
        ....
        return cell
    } else {
        let cell = yourSecondCollectionView.dequeueReusableCell(...) as yourCell
        ....
        return cell
    }
    

    【讨论】:

      【解决方案2】:

      根据您的错误,您的重用标识符与情节提要中的任何单元格都不匹配。在界面生成器中单击您的 extera_info collectionView 单元格。选择属性检查器选项卡。在 reuse identifier 下确保您放入 extera_infoCollectionViewCell

      【讨论】:

      • 正如您在我的代码中看到的那样,集合视图单元格代码将选择应该使用哪个单元格,在故事板中,我在重用标识符中写下了单元格的名称
      • 错误信息表示sting不在情节提要中;这是情节提要中的问题,而不是代码中的问题。
      • 您可以在照片中看到我在故事板中完成的操作
      【解决方案3】:

      如果你把其他tableview单元格放在不同的类中,故事板的NSObject特性可以帮助你,并且易于维护。

      【讨论】:

      • 它还需要一个故事板,
      【解决方案4】:

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

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

      您使用的每个 Collection View 都需要自己的 dequeueReusableCell 标识符:

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

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

      瞧,您现在拥有一个 collectionView 数据源集所需的方法,但服务于您的所有集合视图。甚至更好的是,当有人扩展项目并添加另一个 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 但忘记添加 switch case,则可能会发生错误-因此请让您的错误语句准确地解释问题所在。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-07-23
        • 1970-01-01
        • 1970-01-01
        • 2016-07-20
        相关资源
        最近更新 更多