Reputation: 2302
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
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