mkz
mkz

Reputation: 2302

CollectionView in tableViewCell data display

I have a collectionView embedded in each tableViewCell. On each tableViewWillDisplayCell event I set correct dataSource for my collectionView and then reload data in collectionView.

Here is the code:

override func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {
    let c = cell as! CustomTableViewCell
    c.setCollectionViewDataSourceDelegate(dataSourceDelegate: self, indexPath: indexPath)
}

CustomTableViewCell.swift:

class CustomTableViewCell: UITableViewCell {

var collectionView: indexedCollectionView!

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

    var layout: UICollectionViewFlowLayout = UICollectionViewFlowLayout()
    layout.sectionInset = UIEdgeInsets(top: 5, left: 5, bottom: 5, right: 5)
    layout.itemSize = CGSizeMake(5, 5)
    layout.scrollDirection = UICollectionViewScrollDirection.Horizontal
    self.collectionView = indexedCollectionView(frame: CGRectZero, collectionViewLayout: layout)
    self.collectionView.registerClass(UICollectionViewCell.classForCoder(), forCellWithReuseIdentifier: collectionViewCellIdentifier as String)
    self.collectionView.backgroundColor = UIColor.whiteColor()
    self.collectionView.showsHorizontalScrollIndicator = false
    self.contentView.addSubview(self.collectionView)
}

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

override func layoutSubviews() {
    super.layoutSubviews()
    self.collectionView.frame = self.contentView.bounds;
}

func setCollectionViewDataSourceDelegate(dataSourceDelegate delegate: protocol<UICollectionViewDelegate,UICollectionViewDataSource>, indexPath: NSIndexPath){
    self.collectionView.dataSource = delegate
    self.collectionView.delegate = delegate
    self.collectionView.indexPath = indexPath
    self.collectionView.tag = indexPath.row
    self.collectionView.reloadData()
}

}

TableViewController.swift:

func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
    let cell: UICollectionViewCell = collectionView.dequeueReusableCellWithReuseIdentifier("CollectionViewCell", forIndexPath: indexPath) as! UICollectionViewCell
    let tableViewCell = self.tableView.cellForRowAtIndexPath(NSIndexPath(forItem: collectionView.tag, inSection: 0))
    var rect: CGRect?

    var label: UILabel = UILabel()
    label.font = UIFont(name: "HelveticaNeue-Light", size: 18.0)
    label.numberOfLines = 0
    label.lineBreakMode = NSLineBreakMode.ByWordWrapping
    label.textAlignment = .Center
    switch indexPath.row {
    case 0:
        cell.frame = CGRectMake(0, 0, tableViewCell!.frame.width * 0.2, tableViewCell!.frame.height)
        rect = cell.bounds
        label.frame = rect!
        label.text = events[collectionView.tag].category
        break
    case 1:
        cell.frame = CGRectMake(tableViewCell!.frame.width * 0.2, 0, tableViewCell!.frame.width * 0.3, tableViewCell!.frame.height)
        rect = cell.bounds
        label.frame = rect!
        label.text = events[collectionView.tag].event
        break
    case 2:
        cell.frame = CGRectMake(tableViewCell!.frame.width * 0.5, 0, tableViewCell!.frame.width * 0.26, tableViewCell!.frame.height)
        rect = cell.bounds
        label.frame = rect!
        label.text = events[collectionView.tag].location
        break
    case 3:
        cell.frame = CGRectMake(tableViewCell!.frame.width * 0.76, 0, tableViewCell!.frame.width * 0.12, tableViewCell!.frame.height)
        rect = cell.bounds
        label.frame = rect!
        label.text = events[collectionView.tag].date
        break
    case 4:
        cell.frame = CGRectMake(tableViewCell!.frame.width * 0.88, 0, tableViewCell!.frame.width * 0.12, tableViewCell!.frame.height)
        rect = cell.bounds
        label.frame = rect!
        label.text = events[collectionView.tag].time
        break
    default:
        break
    }
    cell.addSubview(label)
    cell.layer.borderColor = UIColor.blackColor().CGColor
    cell.layer.borderWidth = 0.5

    return cell
}

When application launch everything looks fine (screenshot) but when I scroll my tableView it become to fire tableView willDisplayCell event again for each cell which fires their collectionView's reloadData.

But it doesn't works well (screenshot). Can someone help me with my problem?

UPDATE:

I have tried to remake my code but i've got a problem. Here is my whole code:

class TableViewController: UITableViewController {//, UICollectionViewDataSource, UICollectionViewDelegate {

var events: [Event] = [
    Event(category: "GAA - Football Campionship", event: "Round 4A Munster Final Runner up v Round 3A Winner", location: "Semple Stadium - Thurles", date: "7/12/15", time: "2:00pm"),
    Event(category: "Football", event: "Round 4A Munster", location: "Thurles", date: "7/2/15", time: "All day"),
    Event(category: "Golf - 4 Majors", event: "U.S. Open Day 4 ( Final Day)", location: "Oakmont Country Club, Pennsylvania", date: "7/12/15", time: ""),
]

override func viewDidLoad() {
    super.viewDidLoad()

    //self.tableView.registerClass(CustomTableViewCell.self, forCellReuseIdentifier: "Cell")
    self.tableView.separatorStyle = .None
    self.tableView.tableFooterView = UIView(frame: CGRectZero)
}

// MARK: - Table view data source

override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
    return 1
}

override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return events.count
}

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    var cell: CustomTableViewCell? = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as? CustomTableViewCell

    if cell == nil {
        cell = CustomTableViewCell.CreateCustomCell()
    }
    cell!.event = events[indexPath.row]
    cell!.size = CGSize(width: cell!.frame.width, height: cell!.frame.height)
    cell!.collectionView.reloadData()
    cell!.clipsToBounds = true

    return cell!
}

//    override func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {
//        let c = cell as! CustomTableViewCell
//        c.setCollectionViewDataSourceDelegate(dataSourceDelegate: self, indexPath: indexPath)
//    }

override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
    var cellHeight: CGFloat = 0.0
    let screenWidth: CGFloat = UIScreen.mainScreen().bounds.width

    var question: NSString = events[indexPath.row].category
    var size = CGSizeMake(screenWidth * 0.2, 9999)
    var textRect = question.boundingRectWithSize(size, options: NSStringDrawingOptions.UsesLineFragmentOrigin, attributes: [NSFontAttributeName: UIFont(name: "HelveticaNeue-Light", size: 18.0)!], context: nil)
    size = textRect.size
    cellHeight = size.height

    question = events[indexPath.row].event
    size = CGSizeMake(screenWidth * 0.3, 9999)
    textRect = question.boundingRectWithSize(size, options: NSStringDrawingOptions.UsesLineFragmentOrigin, attributes: [NSFontAttributeName: UIFont(name: "HelveticaNeue-Light", size: 18.0)!], context: nil)
    size = textRect.size
    if cellHeight < size.height {
        cellHeight = size.height
    }

    question = events[indexPath.row].location
    size = CGSizeMake(screenWidth * 0.3, 9999)
    textRect = question.boundingRectWithSize(size, options: NSStringDrawingOptions.UsesLineFragmentOrigin, attributes: [NSFontAttributeName: UIFont(name: "HelveticaNeue-Light", size: 18.0)!], context: nil)
    size = textRect.size
    if cellHeight < size.height {
        cellHeight = size.height
    }

    question = events[indexPath.row].date
    size = CGSizeMake(screenWidth * 0.1, 9999)
    textRect = question.boundingRectWithSize(size, options: NSStringDrawingOptions.UsesLineFragmentOrigin, attributes: [NSFontAttributeName: UIFont(name: "HelveticaNeue-Light", size: 18.0)!], context: nil)
    size = textRect.size
    if cellHeight < size.height {
        cellHeight = size.height
    }

    question = events[indexPath.row].time
    size = CGSizeMake(screenWidth * 0.1, 9999)
    textRect = question.boundingRectWithSize(size, options: NSStringDrawingOptions.UsesLineFragmentOrigin, attributes: [NSFontAttributeName: UIFont(name: "HelveticaNeue-Light", size: 18.0)!], context: nil)
    size = textRect.size
    if cellHeight < size.height {
        cellHeight = size.height
    }

    return cellHeight
}
}

CustomTableViewCell.swift:

class CustomTableViewCell: UITableViewCell, UICollectionViewDataSource, UICollectionViewDelegate {

//var collectionView: UICollectionView!
@IBOutlet weak var collectionView: UICollectionView!

var event: Event?
var size: CGSize?

override func awakeFromNib() {
    super.awakeFromNib()
    println("awake")

    var layout: UICollectionViewFlowLayout = UICollectionViewFlowLayout()
    layout.sectionInset = UIEdgeInsets(top: 5, left: 5, bottom: 5, right: 5)
    layout.itemSize = CGSizeMake(5, 5)
    layout.scrollDirection = UICollectionViewScrollDirection.Horizontal
    collectionView.collectionViewLayout = layout
    //self.collectionView = indexedCollectionView(frame: CGRectZero, collectionViewLayout: layout)
    collectionView.registerClass(CustomCollectionViewCell.self, forCellWithReuseIdentifier: "CollectionViewCell")
    collectionView.backgroundColor = UIColor.whiteColor()
    collectionView.showsHorizontalScrollIndicator = false
    var cNib:UINib? = UINib(nibName: "CustomCollectionViewCell", bundle: nil)
    collectionView.registerNib(cNib, forCellWithReuseIdentifier: "CollectionViewCell")
    collectionView.frame = self.bounds
    //self.contentView.addSubview(self.collectionView)

}

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

//        var layout: UICollectionViewFlowLayout = UICollectionViewFlowLayout()
//        layout.sectionInset = UIEdgeInsets(top: 5, left: 5, bottom: 5, right: 5)
//        layout.itemSize = CGSizeMake(5, 5)
//        layout.scrollDirection = UICollectionViewScrollDirection.Horizontal
//        self.collectionView = indexedCollectionView(frame: CGRectZero, collectionViewLayout: layout)
//        self.collectionView.registerClass(UICollectionViewCell.classForCoder(), forCellWithReuseIdentifier: collectionViewCellIdentifier as String)
//        self.collectionView.backgroundColor = UIColor.whiteColor()
//        self.collectionView.showsHorizontalScrollIndicator = false
//        self.contentView.addSubview(self.collectionView)
}

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

//    override func layoutSubviews() {
//        super.layoutSubviews()
//        self.collectionView.frame = self.contentView.bounds;
//    }

//    func setCollectionViewDataSourceDelegate(dataSourceDelegate delegate: protocol<UICollectionViewDelegate,UICollectionViewDataSource>, indexPath: NSIndexPath){
//        self.collectionView.dataSource = delegate
//        self.collectionView.delegate = delegate
//        self.collectionView.indexPath = indexPath
//        self.collectionView.tag = indexPath.row
//        self.collectionView.reloadData()
//    }

// MARK: - Collection view data source

func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int {
    return 1
}

func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    return 5
}

func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
    let cell: CustomCollectionViewCell = collectionView.dequeueReusableCellWithReuseIdentifier("CollectionViewCell", forIndexPath: indexPath) as! CustomCollectionViewCell
    //let tableViewCell = tableView!.cellForRowAtIndexPath(NSIndexPath(forItem: collectionView.tag, inSection: 0))
    var rect: CGRect?

    var label: UILabel = UILabel()
    label.font = UIFont(name: "HelveticaNeue-Light", size: 18.0)
    label.numberOfLines = 0
    label.lineBreakMode = NSLineBreakMode.ByWordWrapping
    label.textAlignment = .Center
    switch indexPath.row {
    case 0:
        cell.frame = CGRectMake(0, 0, size!.width * 0.2, size!.height)
        rect = cell.bounds
        label.frame = rect!
        label.text = event!.category
        break
    case 1:
        cell.frame = CGRectMake(size!.width * 0.2, 0, size!.width * 0.3, size!.height)
        rect = cell.bounds
        label.frame = rect!
        label.text = event!.event
        break
    case 2:
        cell.frame = CGRectMake(size!.width * 0.5, 0, size!.width * 0.26, size!.height)
        rect = cell.bounds
        label.frame = rect!
        label.text = event!.location
        break
    case 3:
        cell.frame = CGRectMake(size!.width * 0.76, 0, size!.width * 0.12, size!.height)
        rect = cell.bounds
        label.frame = rect!
        label.text = event!.date
        break
    case 4:
        cell.frame = CGRectMake(size!.width * 0.88, 0, size!.width * 0.12, size!.height)
        rect = cell.bounds
        label.frame = rect!
        label.text = event!.time
        break
    default:
        break
    }
    cell.addSubview(label)
    cell.layer.borderColor = UIColor.blackColor().CGColor
    cell.layer.borderWidth = 0.5

    return cell
}

class func CreateCustomCell() -> CustomTableViewCell
{
    var nibElements: Array = NSBundle.mainBundle().loadNibNamed("CustomTableViewCell", owner: self, options: nil)
    var item: AnyObject?
    for item in nibElements
    {
        if item is UITableViewCell
        {
            return item as! CustomTableViewCell
        }
    }
    return item as! CustomTableViewCell
}
}

CustomCollectionViewCell.swift

class CustomCollectionViewCell: UICollectionViewCell {

override init(frame: CGRect) {
    super.init(frame: frame)

}

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

override func awakeFromNib() {
    super.awakeFromNib()

}
}

Also, in storyboard I added a collectionView to my tableViewCell, connected it to outlet variable and set CustomCollectionCell class to collectionCell in storyboard.

But when I launch the app it thrown an exception on this line in tableViewCellForRowAtIndexPath:

2015-07-16 13:29:00.965 CollectionViewInTableViewCell[4241:1005396] Terminating app due to uncaught exception NSUnknownKeyException, reason: [CollectionViewInTableViewCell.CustomTableViewCell 0x126e12440 setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key collection.'

Upvotes: 1

Views: 1569

Answers (1)

matthias
matthias

Reputation: 947

Your CustomTableViewCell has to implement the UICollectionViewDelegate and the UICollectionViewDataSource and the cell itself has to be linked to the delegate and datasource when adding it to the table view.

Upvotes: 0

Related Questions