I have a collection view nested in a table view. The collection view cells are not loading. I am not able to set the collection view delgate and dataSource in the tableViewCell init function because it unwraps as nil, so i created a load function that is called to set it when the cell loads. The issue I have now is that the dataSource/delgate functions are not being called and the table view cell is not loading. My collection view cell for now is just an image, so didn't include that. Also, I have checked that all these outlets are connected correctly, and the table view cell and collection view cell both have reuse identifies set through interface builder. Here is my code:
View Controller:
#IBOutlet weak var libraryTableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
self.libraryTableView.dataSource = self
self.libraryTableView.delegate = self
// Do any additional setup after loading the view.
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: "LibraryTableViewCell", for: indexPath) as? LibraryTableViewCell else {
return LibraryTableViewCell()
}
cell.load()
return cell
}
Table View Cell:
#IBOutlet weak var carouselLabel: UILabel!
#IBOutlet weak var carousel: UICollectionView!
func load() {
layer.backgroundColor = UIColor.clear.cgColor
carouselLabel.text = "hello world"
carousel.delegate = self
carousel.dataSource = self
//carousel.reloadData()
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 1
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "packCell", for: indexPath) as? PackCollectionViewCell else {
return PackCollectionViewCell()
}
return cell
}
Related
There is a very similar question here, but the solution doesn't solve anything for me, mainly because my embedded collection view is already inside the table view cell's content view (I created it in storyboard).
Is there some setting that I need to check to allow my collection view to scroll? It seems that the parent table view cell is eating up all gestures.
TableViewController.swift
class TableViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, UICollectionViewDataSource, UICollectionViewDelegate {
#IBOutlet weak var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
tableView.dataSource = self
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! CustomTableViewCell
cell.collectionView.dataSource = self
cell.collectionView.delegate = self
return cell
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 5
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "collectionCell", for: indexPath)
return cell
}
}
CustomTableViewCell.swift
class CustomTableViewCell: UITableViewCell {
#IBOutlet weak var collectionView: UICollectionView!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
You can find my demo project here
https://github.com/MattiaPell/CollectionView-inside-a-TableViewCell
Turns out in my case it was simple as not having User Interaction Enabled check marked for my child collection view.
My purpose is to show the header string in each label of collectionview cell.But when I run the top cells which have already loaded are showing correct values in labels while after scrolling the reused cells are showing incorrect values.
Note : The data is fetched from a local file.
My data is as follows:
Trending : 20 items
Mustwatch : 3 items
Newly Added : 8 Items
Popular : 2 items
My code:
ViewController.swift
import UIKit
class ViewController: UIViewController,UITableViewDataSource,UITableViewDelegate {
var videosList:[VideosJSONElement]?
var videosListInstance:VideosDataAccessModel?
#IBOutlet weak var categoriesTableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
videosListInstance = VideosDataAccessModel()
videosList = videosListInstance?.videosList
categoriesTableView.dataSource = self
categoriesTableView.delegate = self
categoriesTableView.reloadData()
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return videosList!.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
var cell = tableView.dequeueReusableCell(withIdentifier: "categoriesCell") as! CategoriesVideoCell
cell.videos = videosList![indexPath.row].nodes
cell.position = indexPath.row
cell.categoryTitle.text = videosList![indexPath.row].title
cell.videosCollectionView.reloadData()
cell.sceneContext = self
return cell
}
}
CategoriesVideoCell.swift
import UIKit
class CategoriesVideoCell: UITableViewCell,UICollectionViewDelegate,UICollectionViewDataSource {
#IBOutlet weak var categoryTitle: UILabel!
var videos:[Node]?
var position:Int!
var sceneContext:UIViewController?
#IBOutlet weak var videosCollectionView: UICollectionView!
override func didMoveToSuperview() {
super.didMoveToSuperview()
videosCollectionView.dataSource = self
videosCollectionView.delegate = self
}
override class func awakeFromNib() {
super.awakeFromNib()
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return videos!.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell
{
var cell = collectionView.dequeueReusableCell(withReuseIdentifier: "videoCell", for:indexPath) as! VideoCVCell
cell.node = "\(categoryTitle.text!)"
return cell
}}
The first two cells have correct label text
The reused cells have incorrect data in the label
I am Trying to Create a Table View which is
Expandable
It's Childview has a UICollectionView
UICollectionView is Dynamically rendered using API
onTouch Event of UICollectionView Item should be taken care of
Tried couple of samples didn't work
import UIKit
extension String{
func print(){
Swift.print(self)
}
func log(){
Swift.print(self)
}
}
class CustomVCViewController: UIViewController, UITableViewDataSource, UITableViewDelegate , UICollectionViewDataSource, UICollectionViewDelegate{
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 5
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "ccell", for: indexPath) as! CustomCollectionViewCell
cell.backgroundColor = UIColor.blue
return cell
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 10
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
"Selection of Collection View item at \(indexPath.row)".print()
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
"Selection of Table View item at \(indexPath.row)".print()
}
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell",for: indexPath) as! CustomTableViewCell
cell.innerCollectionView.dataSource = self
cell.innerCollectionView.delegate = self
cell.backgroundColor = UIColor.red
return cell
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
#IBOutlet weak var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
tableView.dataSource = self
// Do any additional setup after loading the view.
}
}
This is for the table view cell
import UIKit
class CustomTableViewCell: UITableViewCell {
#IBOutlet weak var innerCollectionView: UICollectionView!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
According to my understanding you want the tableviewcell to be expandable as collection view so Im adding the code for it , the thing is collectionview is not invalidating its first internsic content size accordingly
/// This CollectionView class is used to invalidate collectionview's default implementation of inrinsic content size
class DynamicCollectionView: UICollectionView {
override func layoutSubviews() {
super.layoutSubviews()
if !__CGSizeEqualToSize(bounds.size, self.intrinsicContentSize) {
self.invalidateIntrinsicContentSize()
}
}
override var intrinsicContentSize: CGSize {
return collectionViewLayout.collectionViewContentSize
}
}
SO add this class to your collectionview and provide flowlayout to your collectionviewcells. also!!! return UITableViewAutomaticDimension on heightforRowAt of tableview.
I am working on a meme generator app. The meme generator is presented modally and is built into a tab bar view controller. The first tab displays all saved memes in a table view and the second is intended to display the saved memes in a collection view. The meme generator works as design and is saving generated memes to an array that is located in the App Delegate file (I know this is controversial, but it is a requirement of the exercise). I am attempting to set up the collection view and I am not able to get a reference to the meme object in the app delegate file and I don't understand why.
import UIKit
class CollectionViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource {
#IBOutlet weak var collectionView: UICollectionView!
var memes: [Meme]! {
didSet {
collectionView.reloadData()
}
}
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
let appDelegate = UIApplication.shared.delegate as! AppDelegate
memes = appDelegate.memes
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return memes.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath)
cell.imageView.image = memes[indexPath].memedImage
return cell
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
}
}
I based this code on the code used for my table view, which works as designed. That code is:
import UIKit
class TableViewMemesViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var tableView: UITableView!
var memes: [Meme]! {
didSet {
tableView.reloadData()
}
}
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
let appDelegate = UIApplication.shared.delegate as! AppDelegate
memes = appDelegate.memes
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return memes.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell")
let meme = memes[indexPath.row]
cell?.imageView?.image = meme.memedImage
cell?.textLabel?.text = meme.topText
return cell!
}
}
How can I get a reference to the array data and display it inside of the collection view when the user saves a new meme? Here is a link to the repo.
You have some issues, first you have to create a Custom CollectionViewCell:
class Cell: UICollectionViewCell {
#IBOutlet var imageView:UIImageView!
}
remember to set the Custom Class for UICollectionViewCell inside the storyboard:
then when you dequeue the cell, be sure of as! Cell:
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) as! Cell
cell.imageView.image = memes[indexPath.row].memedImage
return cell
}
Then inside your TabBarStoryboard.storyboard, you must set delegate and datasource for your CollectionViewController (I checked your github, you didn't attach them).
Finally the result will be:
I have a tableView in which I have 2 custom cells, in both cells I have different CollectionView, the dataSource and delegate of both the CollectionViews is my ViewController.
So now how do I check which CollectionViews is to be configured in UICollectionView's respective methods?
Here is the view hierarchy
How do I come to know which is the collectionView that's there in the parameter of above function?
So here is my code:
class FeatureBannerTableViewCell: UITableViewCell {
#IBOutlet weak var featureCollectionView: UICollectionView!
}
class FeaturedTableViewCell: UITableViewCell {
#IBOutlet weak var FeatureTitle: UILabel!
#IBOutlet weak var seeAllButton: UIButton!
#IBOutlet weak var collectionView: UICollectionView!
}
extension ViewController: UITableViewDataSource {
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
switch indexPath.row {
case 2,3,6,7:
let cell = featuredTableView.dequeueReusableCellWithIdentifier("FeatureBannerTableViewCell", forIndexPath: indexPath) as! FeatureBannerTableViewCell
cell.featureCollectionView.dataSource = self
cell.featureCollectionView.delegate = self
return cell
default:
let cell = featuredTableView.dequeueReusableCellWithIdentifier("FeaturedTableViewCell", forIndexPath: indexPath) as! FeaturedTableViewCell
cell.collectionView.dataSource = self
cell.collectionView.delegate = self
return cell
}
}
}
extension ViewController: UICollectionViewDataSource {
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
// how do I know if this collectionView is collectionView or featureCollectionView?
}
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
// how do I know if this collectionView is collectionView or featureCollectionView?
}
}
I would use the tag property in UIView to identify your collection view. So when you configure your table cells in cellForRowAtIndexPath get the collection view of the cell and set its tag to something unique (I would use the row value of indexpath).
extension ViewController: UITableViewDataSource {
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
switch indexPath.row {
case 2,3,6,7:
let cell = featuredTableView.dequeueReusableCellWithIdentifier("FeatureBannerTableViewCell", forIndexPath: indexPath) as! FeatureBannerTableViewCell
cell.featureCollectionView.dataSource = self
cell.featureCollectionView.delegate = self
cell.featureCollectionView.tag = indexPath.row
return cell
default:
let cell = featuredTableView.dequeueReusableCellWithIdentifier("FeaturedTableViewCell", forIndexPath: indexPath) as! FeaturedTableViewCell
cell.collectionView.dataSource = self
cell.collectionView.delegate = self
cell.collectionView.tag = indexPath.row
return cell
}
}
}
Then in your collection view methods get the tag value and that will tell you which one of the many collection views it is.
extension ViewController: UICollectionViewDataSource {
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
// how do I know if this collectionView is collectionView or featureCollectionView?
let datasourceIndex = collectionView.tag
// now use your datasource for the following index
}
}
I think, you can make use of isKindOfClass
Example:
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
// get a reference to our storyboard cell
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "MyReuseIdentifier", for: indexPath as IndexPath) as! UICollectionViewCell
if cell.isKindOfClass(FeaturedBannerCollectionCell){
//implementation code
} else cell.isKindOfClass(FeaturedCollectionViewCell) {
//implementation code
}
return cell
}