Swift Collcetionview didSelectItemAtIndexPath not working - ios

In myscenario, I am using UICollectionView in Storyboard. The didSelectItemAtIndexPath not working. I have added Imageview on UICollectionView and using customcell.
CollectionView CustomCell
class CustomCollectionViewCell: UICollectionViewCell {
#IBOutlet weak var imageView: UIImageView!
override func draw(_ rect: CGRect) {
super.draw(rect)
self.layer.cornerRadius = self.frame.size.width / 2
}
}
My CollectionView Delegates
class ModernViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
#IBOutlet weak var collectionView: UICollectionView!
override func viewDidLoad() {
super.viewDidLoad()
collectionView.delegate = self
collectionView.dataSource = self
collectionView.allowsSelection = true
}
// MARK: CollectionView Delegate
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return self.listData
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath as IndexPath) as! CustomCollectionViewCell
let item = self.listData[indexPath.item]
let url = item.profileimage
cell.imageView?.sd_setImage(with: URL(string: url ?? "sample.png"), placeholderImage: UIImage(named: "sample.png"))
return cell
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: 35.0, height: 35.0)
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
print("You selected cell #\(indexPath.item)!")
//let item = self.listData[indexPath.item]
//print("SELECTED COLLECTION CELL: \(item.firstname ?? "")")
}
}

remove this line from collectionViewCell class
self.layer.cornerRadius = self.frame.size.width
updated code
class CustomCollectionViewCell: UICollectionViewCell {
#IBOutlet weak var imageView: UIImageView!
override func draw(_ rect: CGRect) {
super.draw(rect)
// self.layer.cornerRadius = self.frame.size.width / 2 // remove this line
}
}
I think you need to set cornerRadius of imageView instead of cell.
self.imageView.layer.cornerRadius = self.frame.size.width/ 2

Related

CollectionView delegate methods are not calling from TableViewCell

Delegate isn't being called from tableViewCell. Here is UICollectionViewDelegate and UICollectionViewDataSource code
extension HomeVC:UICollectionViewDataSource,UICollectionViewDelegate,UICollectionViewDelegateFlowLayout{
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 4
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "ProductCell", for: indexPath)
return cell
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
print("ok")
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let lay = collectionViewLayout as! UICollectionViewFlowLayout
lay.sectionInset = UIEdgeInsets(top: 0, left: 5, bottom: 0, right: 5)
lay.minimumInteritemSpacing = 0
lay.minimumLineSpacing = 0
collectionView.collectionViewLayout = lay
let size = (collectionView.frame.size.width-10) / 2
return CGSize(width: size, height: size)
}
}
swift 5
//MARK:- Tableview Datasource method
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier:"RecentLoanApplicationCell") as! RecentLoanApplicationCell
cell.collectionVC.delegate = self
cell.collectionVC.dataSource = self
cell.btnViewAll.addTarget(self, action: #selector(btnViewALLTap(button:)), for: .touchUpInside)
DispatchQueue.main.async {
cell.collectionVC.reloadData()
}
return cell
}
//MARK:- Tableview Cell in side custom cell Register for collectionView cell
class RecentLoanApplicationCell: UITableViewCell {
#IBOutlet var collectionVC:UICollectionView!
override func awakeFromNib() {
super.awakeFromNib()
self.collectionVC.register(UINib.init(nibName:"RecentLoanCollectionViewCell", bundle: nil), forCellWithReuseIdentifier:"RecentLoanCollectionViewCell")
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
}
}
// Same ControllerView call
//MARK:- Collection DataSource & Delegate
extension HomeViewController : UICollectionViewDelegate,UICollectionViewDataSource {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 5
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier:"RecentLoanCollectionViewCell", for: indexPath) as! RecentLoanCollectionViewCell
return cell
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
debugPrint("didSelectItemAt ==>\(indexPath.row)")
}
Here is the code how I done for same inside TableViewCell using collectionView and performed selection :
Code inside TableView datasource method :
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "BasicCarColorCell", for: indexPath) as! BasicCarColorCell
cell.dataSource = preloads.colors
cell.collectionViewSetup()
cell.delegate = self
return cell
}
Code for TableViewCell:
protocol BasicCarColorCellDelegate {
func colorCell(cell:BasicCarColorCell, didSelect color: Color)
}
class BasicCarColorCell: UITableViewCell {
var dataSource = Array<Color>()
var selectedColor = Color()
#IBOutlet weak var textView: RSKPlaceholderTextView!
#IBOutlet weak var guideLineMessage:UILabel!
#IBOutlet weak var collectionView: UICollectionView!
var delegate: BasicCarColorCellDelegate?
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
func collectionViewSetup() {
let nib = UINib(nibName: "BasicCarColorCollectionCell", bundle: nil)
self.collectionView.register(nib, forCellWithReuseIdentifier: "BasicCarColorCollectionCell")
let flowLayout = UICollectionViewFlowLayout()
flowLayout.minimumLineSpacing = 0
flowLayout.minimumInteritemSpacing = 0
flowLayout.scrollDirection = .horizontal
collectionView.collectionViewLayout = flowLayout
collectionView.dataSource = self
collectionView.delegate = self
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
extension BasicCarColorCell: UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return self.dataSource.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "BasicCarColorCollectionCell", for: indexPath) as! BasicCarColorCollectionCell
return cell
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let height = collectionView.bounds.size.height-2
let width = height-20
return CGSize(width: width, height:height)
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
return UIEdgeInsets(top: 1, left: 10, bottom: 1, right: 10)
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let color = self.dataSource[indexPath.item]
self.selectedColor = color
delegate?.colorCell(cell: self, didSelect: self.selectedColor)
collectionView.reloadData()
}
}
And to handle the selection of collectionView just implement the method of custom protocol written in TableViewCell in ViewController:
func colorCell(cell: BasicCarColorCell, didSelect color: Color) {
//self.selectedCarColor = color.value
}
You can do it in same pattern as per your need.
Hope it'll help!
You need to set datasource and delegate for collectionView, every time in Tableview delegate CellForRowAtIndexPath.

How to add Footer / Header in CollectionView

code Snippet
class TemporaryViewController: UIViewController {
#IBOutlet weak var itemCollectionView: UICollectionView! // Main Collection View
private var footerView: DashboardBottomViewCollectionViewCell?
override func viewDidLoad() {
super.viewDidLoad()
self.itemCollectionView.delegate = self
self.itemCollectionView.dataSource = self
self.itemCollectionView.register(UINib(nibName: nibParameter.DASHBOARD_CENTER_NIB, bundle: nil), forCellWithReuseIdentifier: nibParameter.DASHBOARD_CENTER_NIB)
self.itemCollectionView.register(UINib(nibName: "DashboardBottomViewCollectionViewCell", bundle: nil), forSupplementaryViewOfKind: UICollectionView.elementKindSectionFooter, withReuseIdentifier: "DashboardBottomViewCollectionViewCell")
}}
extension TemporaryViewController: UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
switch kind {
case UICollectionView.elementKindSectionHeader:
return nil
case UICollectionView.elementKindSectionFooter:
let footerView = itemCollectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "DashboardBottomViewCollectionViewCell", for: indexPath) as! DashboardBottomViewCollectionViewCell
self.footerView = footerView
self.footerView?.contentView?.clipsToBounds = true
footerView?.dashboardBottomDelegate = self
footerView?.clipsToBounds = true
return footerView!
default:
return headerView!
}
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize {
return CGSize(width: 600, height: 300.0)
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForFooterInSection section: Int) -> CGSize {
return CGSize(width: 100.0, height: 300.0)
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 3
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let width = -10 + (collectionView.frame.width)
return CGSize(width: width,
height: 90)
}
}
Footer Class to Show collection View
class DashboardBottomViewCollectionViewCell: UICollectionReusableView {
weak var dashboardBottomDelegate: DashboardBottomViewCollectionViewDelegate?
#IBOutlet weak var itemCollectionView: UICollectionView!
#IBOutlet weak var imageView: UIView!
var estimateWidth = 160.0
var cellMarginSize = 16.0
var contentView : DashboardBottomViewCollectionViewCell?
override init(frame: CGRect) {
super.init(frame: frame)
let contents = Bundle.main.loadNibNamed("DashboardBottomViewCollectionViewCell", owner: self, options: nil)?.first as! DashboardBottomViewCollectionViewCell
self.addSubview(contents)
contentView = contents
contents.itemCollectionView.register(UINib(nibName: nibParameter.DASHBOARD_PURCHASE_NIB, bundle: nil), forCellWithReuseIdentifier:nibParameter.DASHBOARD_PURCHASE_NIB)
contents.itemCollectionView.delegate = self
contents.itemCollectionView.dataSource = self
let flow = contents.itemCollectionView?.collectionViewLayout as! UICollectionViewFlowLayout
flow.minimumInteritemSpacing = CGFloat(self.cellMarginSize)
flow.minimumLineSpacing = CGFloat(self.cellMarginSize)
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
func reloadData() {
contentView?.itemCollectionView.reloadData()
}
}
extension DashboardBottomViewCollectionViewCell: UICollectionViewDataSource {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 15
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: nibParameter.DASHBOARD_PURCHASE_NIB, for: indexPath) as! RecentPurchaseCollectionViewCell
cell.purchaseLabel.text = "trainers.trainerName"
cell.imageView.sd_setImage(with: URL(string: "trainers.tarinerProfilePictureUrl" != nil ? "trainers.tarinerProfilePictureUrl" : ""), placeholderImage: UIImage.init(named: "tour_placeholder"), options: .handleCookies, completed: nil)
return cell
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let width = 0 + (collectionView.frame.width / 1)
return CGSize(width: width,
height: 100)
}
}
extension DashboardBottomViewCollectionViewCell : UICollectionViewDelegate {
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
dashboardBottomDelegate?.didSelect(tem: indexPath.item)
}
}
As per the code, I can see this:
I can see a collectionView in Footer but can't change the orientation to vertical instead of the Grid view like this:
I am stuck and couldn't find any hint. Any hint would be appreciable. Thanks
Have you tried putting your setup code DashboardBottomViewCollectionViewCell.init(frame:) in awakeFromNib() instead?
override func awakeFromNib() {
super.awakeFromNib()
//setup cell and stuffs
}
Also call footerView?.reloadData() to reload the contents.

First cell and last cell are changing each other in UICollectionView

I have MenuItemCollectionView and FoodItemColletionView and I am setting FoodItemCollectionView in MenuItemColletionViewCell.Error happened in first MenuItemCell and last MenuItemCell are changing each other.But sometimes they are appeared right place.I have no idea to fix this error
This is MenuItemCollectionView
func numberOfSections(in collectionView: UICollectionView) -> Int {
print("Food Array Count = \(self.foodArray.count)")
return self.foodArray.count
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 1
}
func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
switch kind {
case UICollectionElementKindSectionHeader:
let headerView = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: RESUABLE_VIEW, for: indexPath) as! CollectionReusableView
headerView.header.text = nameArray[indexPath.section]
return headerView
default:
assert(false, "Unexpected element kind")
}
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let width = UIScreen.main.bounds.width
let height = UIScreen.main.bounds.height/3
return CGSize(width: width, height: height)
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: ITEM_CELL, for: indexPath) as! MenuItemCollectionViewCell
cell.foodArray.removeAll()
cell.foodArray = self.foodArray[nameArray[indexPath.section]]!
print("Cell COol index = \(indexPath.section) , ARrray count = \(cell.foodArray.count)")
return cell
}
This is MenuItemCollectionViewCell and I set up FoodItemColletionView in this
import UIKit
import SDWebImage
class MenuItemCollectionViewCell: UICollectionViewCell ,UICollectionViewDelegate,UICollectionViewDataSource{
#IBOutlet weak var foodItemColletion: UICollectionView!
var foodArray :[Food] = []
var imageArray : [UIImage?] = []
let FOOD_ITEM_CELL : String = "FoodCell"
override func awakeFromNib() {
foodItemColletion.delegate = self
foodItemColletion.dataSource = self
super.awakeFromNib()
}
override func prepareForReuse() {
foodArray.removeAll()
super.prepareForReuse()
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
for food in foodArray{
print("Title Menu item \(food.title)")
}
return foodArray.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: FOOD_ITEM_CELL, for: indexPath) as! FoodItemCollectionViewCell
let foodObj = foodArray[indexPath.row]
cell.foodLabel.text = foodObj.title
cell.foodPrice.text = foodObj.price
cell.foodImage.sd_setImage(with: URL(string: "\(URLS.IMG_URL)\(foodObj.imageUrl)"), placeholderImage: nil, options: .refreshCached, progress: nil, completed: nil)
print("Title Menu Item Cell \(indexPath.item) = \(foodObj.title)")
return cell
}
}
This is FoodItemColletionViewCell
import UIKit
class FoodItemCollectionViewCell: UICollectionViewCell {
#IBOutlet weak var foodImage: UIImageView!
#IBOutlet weak var foodLabel: UILabel!
#IBOutlet weak var foodPrice: UILabel!
#IBOutlet weak var cardView: CardView!
override func awakeFromNib() {
foodImage.layer.masksToBounds = true
foodImage.roundCorners(corners: [.topLeft,.topRight], radius: 5)
cardView.setElevation(points: 1.5)
layer.shouldRasterize = true
layer.rasterizationScale = UIScreen.main.scale
cardView.layer.cornerRadius = 5
}
override func prepareForReuse() {
super.prepareForReuse()
foodImage.image = nil
}
}
extension UIImageView{
func roundCorners(corners:UIRectCorner, radius: CGFloat) {
let path = UIBezierPath(roundedRect: self.bounds, byRoundingCorners: corners, cornerRadii: CGSize(width: radius, height: radius))
let mask = CAShapeLayer()
mask.path = path.cgPath
self.layer.mask = mask
}
}
This is top screen that is actually what I want
This is bottom screen that is actually want I want too
But when i scroll fast again from top to bottom, first cell moved to last cell and last cell moved to first cell.This is what happened what i want to fix
In MenuItemCollectionView change this method:
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: ITEM_CELL, for: indexPath) as! MenuItemCollectionViewCell
cell.foodArray.removeAll()
cell.foodArray = self.foodArray[nameArray[indexPath.section]]!
// add this, or else because of reusing the old data will be presented, even though you have set the new one
cell.foodItemColletion.reloadData()
print("Cell COol index = \(indexPath.section) , ARrray count = \(cell.foodArray.count)")
return cell
}

swift : tableViewcell initialization

I have a custom UITableViewCell class which has a collectionview inside. In this class there's a varaible "nbElements" which contain the number of collectionview cells to display. I want to know how I can initialize the value of nbElements when I create a tableview cell with dequeueReusableCell?
Here is the code of the custom tableview cell:
class CustomTableViewCell: UITableViewCell, UICollectionViewDataSource, UICollectionViewDelegate {
#IBOutlet weak var collectionView: UICollectionView!
#IBOutlet weak var collectionViewHeightConstraint: NSLayoutConstraint!
var nbElements = Int!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
self.collectionView.register(UINib(nibName: "CustomCollectionViewCell", bundle: nil), forCellWithReuseIdentifier: "customCollectionViewCell")
self.collectionViewHeightConstraint.constant = self.collectionView.collectionViewLayout.collectionViewContentSize.height
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return nbElements
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "customCollectionViewCell", for: indexPath)
return cell
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let cellWidth = (self.collectionView.frame.width / 2.0) - 1
let size = CGSize.init(width: cellWidth, height: cellWidth)
return size;
}
}
Here is the code when I create a tableview cell:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "customTableViewCell", for: indexPath) as! CustomTableViewCell
cell.nbElements = 4
return cell
}
Regards.
Trigger reload of collectionView whenever the nbElements is set.
var nbElements = Int! {
didSet {
collectionView.reloadData()
}
}

UICollectionView in a UICollectionViewCell

I am interested in having a collectionview as a part of a collection view cell but for some reason cannot figure out how this would be done. Where would I implement the necessary methods for the cells collectionview?
There's an article that Ash Furrow wrote that explains how to put an UICollectionView inside an UITableViewCell. It's basically the same idea when using it inside an UICollectionViewCell.
Everything is done programatically. No storyboards.
I added a UICollectionView inside my UICollectionViewCell. I also show how to add again a UICollectionViewCell inside the created UICollectionView to have this result
import UIKit
class CategoryCell: UICollectionViewCell, UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout {
private let cellId = "cell"
override init(frame: CGRect) {
super.init(frame: frame)
setupViews()
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
let appsCollectionView: UICollectionView = {
let layout = UICollectionViewFlowLayout()
let collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout)
return collectionView
}()
func setupViews() {
backgroundColor = .blue
addSubview(appsCollectionView)
appsCollectionView.delegate = self
appsCollectionView.dataSource = self
appsCollectionView.register(AppCell.self, forCellWithReuseIdentifier: cellId)
addConstrainstWithFormat("H:|-8-[v0]-8-|", views: appsCollectionView)
addConstrainstWithFormat("V:|[v0]|", views: appsCollectionView)
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 5
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellId, for: indexPath)
return cell
}
}
class AppCell: UICollectionViewCell {
override init(frame: CGRect) {
super.init(frame: frame)
setupViews()
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func setupViews(){
backgroundColor = .red
}
}
My UICollectionViewController
import UIKit
class FeaturedAppsController: UICollectionViewController, UICollectionViewDelegateFlowLayout {
let cellId = "cell"
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
collectionView?.backgroundColor = .white
collectionView?.register(CategoryCell.self, forCellWithReuseIdentifier: cellId)
}
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 3
}
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellId, for: indexPath)
return cell
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(view.frame.width, 150)
}
}
The whole explanation can be found and was developed by "Let´s build that app": https://www.youtube.com/watch?v=Ko9oNhlTwH0&list=PL0dzCUj1L5JEXct3-OV6itP7Kz3tRDmma
This is too late for this answer but it might help others. This is an example of UICollectionView inside a UICollectionViewCell.
Lets start by having a mainCollectionView. Then on each cell of this collection create and initialize a new UICollectionView and right place to do that is in this following delegate of UICollectionView
func collectionView(collectionView: UICollectionView, willDisplayCell cell: UICollectionViewCell, forItemAtIndexPath indexPath: NSIndexPath)
e.g I initialize the MainCollectionViewCell here and then MainCollectionViewCell handles the logic to create a new UICollectionView
guard let collectionViewCell = cell as? MainCollectionViewCell else { return }
collectionViewCell.delegate = self
let dataProvider = ChildCollectionViewDataSource()
dataProvider.data = data[indexPath.row] as NSArray
let delegate = ChildCollectionViewDelegate()
collectionViewCell.initializeCollectionViewWithDataSource(dataProvider, delegate: delegate, forRow: indexPath.row)
collectionViewCell.collectionViewOffset = storedOffsets[indexPath.row] ?? 0
Here is the initializer on MainCollectionViewCell that creates a new UICollectionView
func initializeCollectionViewWithDataSource<D: protocol<UICollectionViewDataSource>,E: protocol<UICollectionViewDelegate>>(dataSource: D, delegate :E, forRow row: Int) {
self.collectionViewDataSource = dataSource
self.collectionViewDelegate = delegate
let flowLayout = UICollectionViewFlowLayout()
flowLayout.scrollDirection = .Horizontal
let collectionView = UICollectionView(frame: self.bounds, collectionViewLayout: flowLayout)
collectionView.registerClass(UICollectionViewCell.self, forCellWithReuseIdentifier: reuseChildCollectionViewCellIdentifier)
collectionView.backgroundColor = UIColor.whiteColor()
collectionView.dataSource = self.collectionViewDataSource
collectionView.delegate = self.collectionViewDelegate
collectionView.tag = row
self.addSubview(collectionView)
self.collectionView = collectionView
collectionView.reloadData()
}
Hope that helps !!
I did an example for this and put in on github. It demonstrates the use UICollectionView inside a UICollectionViewCell.
https://github.com/irfanlone/Collection-View-in-a-collection-view-cell
Easiest solution for collectionview inside collectionview using storyboard and Swift 5
Please refer this link for nested collectionview example
import UIKit
class ParentViewController:UIViewController,UICollectionViewDataSource,UICollectionViewDelegate {
//MARK: Declare variable
//MARK: Decalare outlet
#IBOutlet weak var outerCollectionView: UICollectionView!
#IBOutlet weak var pageControl: UIPageControl!
let outerCount = 4
//MARK: Decalare life cycle methods
override func viewDidLoad() {
super.viewDidLoad()
pageControl.numberOfPages = outerCount
}
//MARK: Collection View delegate methods
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return outerCount
}
//MARK: Collection View datasource methods
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "OuterCell", for: indexPath) as! OuterCollectionViewCell
cell.contentView.backgroundColor = .none
return cell
}
//MARK:- For Display the page number in page controll of collection view Cell
func scrollViewDidScroll(_ scrollView: UIScrollView) {
let visibleRect = CGRect(origin: self.outerCollectionView.contentOffset, size: self.outerCollectionView.bounds.size)
let visiblePoint = CGPoint(x: visibleRect.midX, y: visibleRect.midY)
if let visibleIndexPath = self.outerCollectionView.indexPathForItem(at: visiblePoint) {
self.pageControl.currentPage = visibleIndexPath.row
}
}
}
class OuterCollectionViewCell: UICollectionViewCell ,UICollectionViewDataSource,UICollectionViewDelegate {
#IBOutlet weak var InnerCollectionView: UICollectionView!
override func awakeFromNib() {
super.awakeFromNib()
InnerCollectionView.delegate = self
InnerCollectionView.dataSource = self
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
6
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "InnerCell", for: indexPath) as! InnerCollectionViewCell
cell.contentView.backgroundColor = .green
return cell
}
}
class InnerCollectionViewCell: UICollectionViewCell{
}

Resources