Collection-View-in-a-Table-View-Cell
Collection-View-in-a-Table-View-Cell copied to clipboard
Type 'ViewController' does not conform to protocol 'UICollectionViewDataSource'
Hi!
I'm very very new to coding and especially swift. followed your tutorial and am getting this error at the ViewController extension.
I made things a little different than your code, I am using a TableViewController as the starting point. This is the complete code for the subclass.
import UIKit
public let model: [[UIColor]] = generateRandomData()
class TableViewController: UITableViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Uncomment the following line to preserve selection between presentations
// self.clearsSelectionOnViewWillAppear = false
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
// self.navigationItem.rightBarButtonItem = self.editButtonItem()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: - Table view data source
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 0
}
// next two functions are to display table view cells
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// ajustado
return model.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath)
return cell
}
// [kk2] set the collectionView delegate/datasource and row number one function to be called just before the cell is about to be displayed
override func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {
guard let tableViewCell = cell as? TableViewCell else { return }
tableViewCell.setCollectionViewDataSourceDelegate(self, forRow: indexPath.row)
tableViewCell.collectionViewOffset = storedOffsets[indexPath.row] ?? 0
}
override func tableView(tableView: UITableView, didEndDisplayingCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {
guard let tableViewCell = cell as? TableViewCell else { return }
storedOffsets[indexPath.row] = tableViewCell.collectionViewOffset
}
/*
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("reuseIdentifier", forIndexPath: indexPath)
// Configure the cell...
return cell
}
*/
/*
// Override to support conditional editing of the table view.
override func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool {
// Return false if you do not want the specified item to be editable.
return true
}
*/
/*
// Override to support editing the table view.
override func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
if editingStyle == .Delete {
// Delete the row from the data source
tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Fade)
} else if editingStyle == .Insert {
// Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
}
}
*/
/*
// Override to support rearranging the table view.
override func tableView(tableView: UITableView, moveRowAtIndexPath fromIndexPath: NSIndexPath, toIndexPath: NSIndexPath) {
}
*/
/*
// Override to support conditional rearranging of the table view.
override func tableView(tableView: UITableView, canMoveRowAtIndexPath indexPath: NSIndexPath) -> Bool {
// Return false if you do not want the item to be re-orderable.
return true
}
*/
/*
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
// Get the new view controller using segue.destinationViewController.
// Pass the selected object to the new view controller.
}
*/
}
extension ViewController: UICollectionViewDelegate, UICollectionViewDataSource {
func collectionView(collectionView: UICollectionView, numberOfRowsInSection section: Int) -> Int {
return model[collectionView.tag].count
}
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier("Cell", forIndexPath: indexPath)
cell.backgroundColor = model[collectionView.tag] [indexPath.item]
return cell
}
}
func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
print("Collection view at row \(collectionView.tag) selected index path \(indexPath)")
}
It shows another two errors up there, which are Cannot invoke 'setCollectionViewDataSourceDelegate' with an argument list of type '(TableViewController, forRow: Int)'
and
Use of unresolved identifier 'storedOffsets'
both at one of the same override tableView function.
Any idea of what might be causing the problem?
Hey there! Sorry to hear you're having issues. The storedOffsets problem looks like it's a problem with not having a storedOffsets property on your UITableViewController subclass (which this repo has here). The other issue, the setCollectionViewDataSourceDelegate looks more complicated. Assuming you have the same TableViewCell.swift class as this repo, then I imagine it may be a bug with Swift not inferring that self conforms to UICollectionViewDataSource and UICollectionViewDelegate. Can I ask you to try the following?
let castSelf = self as protocol<UICollectionViewDataSource, UICollectionViewDelegate>
tableViewCell.setCollectionViewDataSourceDelegate(castSelf, forRow: indexPath.row)