[英]Why two collection views in two table view cells won't work in Swift 4?
I read similar questions such as how to have multiple collection view in multiple table view cells and I connected my collection views cells and use identifier names for them but I don't know why I receive this Error:我阅读了类似的问题,例如如何在多个表视图单元格中拥有多个集合视图,并且我连接了我的集合视图单元格并为它们使用了标识符名称,但我不知道为什么会收到此错误:
* Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'could not dequeue a view of kind: UICollectionElementKindCell with identifier extera_infoCollectionViewCell - must register a nib or a class for the identifier or connect a prototype cell in a storyboard' * First throw call stack:
* 由于未捕获的异常“NSInternalInconsistencyException”而终止应用程序,原因:“无法将类型的视图出列:UICollectionElementKindCell 与标识符为 exera_infoCollectionViewCell - 必须为标识符注册一个笔尖或类或连接故事板中的原型单元” *首先抛出调用堆栈:
**Remember that I read Similar questions and the first table view cell with collection view working well and the problem is for second one ** here is my code for main view controller that has a table view and the table view has two cells **请记住,我阅读了类似的问题,第一个表视图单元格与集合视图运行良好,问题是第二个 ** 这是我的主视图控制器代码,它有一个表视图,表视图有两个单元格
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
}
}
and here is the table view codes in same view controller:这是同一视图控制器中的表视图代码:
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
}
here is table view first cell class:这是表格视图第一个单元格类:
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()
}
}
and here is the second tableview cell class:这是第二个 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()
}
}
First step: using Tags - you just need to use tag for them and use if else to choose which collection view has selected with tag so the answer is this :第一步:使用标签 - 你只需要为它们使用标签,并使用 if else 来选择哪个集合视图选择了标签,所以答案是这样的:
if collectionView.tag == 1 {
do some thing//////
}else {
do some thing else}
and you should use this in both cellForRowAtIndexPath and numberOfRows methods you can use this for table view too你应该在 cellForRowAtIndexPath 和 numberOfRows 方法中使用它你也可以将它用于表格视图
Second step: you have to change the name of 'collection view' that you are dequeueing inside the cellForRowAt method in CollectionView data source:第二步:您必须更改要在 CollectionView 数据源中的 cellForRowAt 方法中出列的“集合视图”的名称:
if collectionView.tag == 1 {
let cell = yourFirstCollectionView.dequeueReusableCell(...) as yourCell
....
return cell
} else {
let cell = yourSecondCollectionView.dequeueReusableCell(...) as yourCell
....
return cell
}
According to your error your reuse identifier doesn't match any cell in your storyboard.根据您的错误,您的重用标识符与故事板中的任何单元格都不匹配。 Click on your extera_info collectionView cell in interface builder.
在界面构建器中单击您的 extra_info collectionView 单元格。 Select the attributes inspector tab.
选择属性检查器选项卡。 Under reuse identifier make sure you put in extera_infoCollectionViewCell
在重用标识符下,确保你放入了exera_infoCollectionViewCell
如果你把其他的tableview cell 放在不同的类中,借助storyboard 的NSObject 特性,它可以帮助你,并且易于维护。
Saeed's tag option above is likely the simplest answer, but found his description a little short so adding a more complete answer below for those who've never used tags before...上面赛义德的标签选项可能是最简单的答案,但发现他的描述有点短,所以在下面为那些以前从未使用过标签的人添加一个更完整的答案......
If abiding by MVC and placing collectionView dataSource methods inside the UITableView class (instead of inside the UITableViewCell classes), and wanting to avoid this " error:如果遵守 MVC 并将 collectionView dataSource 方法放置在 UITableView 类中(而不是 UITableViewCell 类中),并且想要避免这个“错误:
Each Collection View you use will need its own dequeueReusableCell identifier:您使用的每个集合视图都需要自己的 dequeueReusableCell 标识符:
Now when you tableView cell calls on the collectionView you've outletted in the TableViewCell classes, it will be able to acquire the proper dequeueReusable ID.现在,当您在 TableViewCell 类中输出的 collectionView 上调用 tableView 单元格时,它将能够获取正确的 dequeueReusable ID。 You can put your data inside each switch case.
您可以将数据放入每个开关盒中。
Voila, you now have ONE collectionView datasource set of required methods, but serving ALL of your collection views.瞧,您现在拥有一组所需方法的 collectionView 数据源,但可以为您的所有集合视图提供服务。 EVEN BETTER, when someone expands the project and adds another collectionView it will be as easy as adding another case to the switch and identifier in the storyboard.
更好的是,当有人扩展项目并添加另一个 collectionView 时,就像向故事板中的开关和标识符添加另一个案例一样简单。
Example code could look like this:示例代码可能如下所示:
// 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()
}
note: you have two options for your default to the switch statement... 1. like above, a generic but empty cell instance 2. throw an error.注意:对于 switch 语句的默认设置,您有两个选项...... 1. 像上面一样,一个通用但空的单元格实例 2. 抛出一个错误。 The error should never throw bc you'll have all the cases, but an error could occur if someone else improves your code and add another collectionView but forgets to to add the switch case-- so make your error statement explain what's wrong precisely.
错误永远不应该抛出 bc 您将拥有所有情况,但是如果其他人改进了您的代码并添加了另一个 collectionView 但忘记添加 switch 案例,则可能会发生错误 - 所以让您的错误声明准确地解释什么是错误的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.