Can i have a CollectionView and a TableView in same View Controller - uitableview

I actually have a view controller in which i am showing product attributes in a table view in the lower half of the View Controller and was showing product thumbnail in table view header. But then i realised that a product can have multiple thumbnails so i should add a collection view in upper half of view controller to show all those thumbnail (scrollable horizontally). I added both datasource and delegate for Collection view (UICollectionViewDataSource, UICollectionViewDelegate) and wrote functions to return number of section, number of rows and cellAtIndex but these functions are not called.
So my query is can i have both collection view and table view in same view controller? If yes, then how?
I am using iOS 8 SDK with swift

class ViewController: UIViewController {
#IBOutlet weak var collView: UICollectionView!
#IBOutlet weak var tblView: UITableView!
var arrMain = NSMutableArray()
var arrDays = ["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"]
var arrSunday = ["No Data Available"]
var arrMonday = ["1","2","3"]
var arrTuesday = ["A","B","C"]
var arrWednesday = ["a","b"]
var arrThursday = ["d","e","f"]
var arrFriday = ["5","6","7"]
var arrSaturdsay = ["X","y","z"]
override func viewDidLoad() {
super.viewDidLoad()
arrMain = (arrSunday as NSArray).mutableCopy() as! NSMutableArray
}
}
extension ViewController: UICollectionViewDelegate,UICollectionViewDataSource{
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return arrDays.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collView.dequeueReusableCell(withReuseIdentifier: "collCell", for: indexPath) as! collCell
cell.lblDays.text = arrDays[indexPath.item]
return cell
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
if indexPath.item == 0 {
arrMain = (arrSunday as NSArray).mutableCopy() as! NSMutableArray
}
else if indexPath.item == 1 {
arrMain = (arrMonday as NSArray).mutableCopy() as! NSMutableArray
}
else if indexPath.item == 2 {
arrMain = (arrTuesday as NSArray).mutableCopy() as! NSMutableArray
}
else if indexPath.item == 3 {
arrMain = (arrWednesday as NSArray).mutableCopy() as! NSMutableArray
}
else if indexPath.item == 4 {
arrMain = (arrThursday as NSArray).mutableCopy() as! NSMutableArray
}
else if indexPath.item == 5 {
arrMain = (arrFriday as NSArray).mutableCopy() as! NSMutableArray
}
else if indexPath.item == 6 {
arrMain = (arrSaturdsay as NSArray).mutableCopy() as! NSMutableArray
}
tblView.reloadData()
}
}
extension ViewController: UITableViewDelegate,UITableViewDataSource{
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return arrMain.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tblView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! tblCell
cell.lblName.text = arrMain[indexPath.row] as? String
return cell
}
}
class tblCell: UITableViewCell{
#IBOutlet weak var lblName: UILabel!
}
class collCell : UICollectionViewCell{
#IBOutlet weak var lblDays: UILabel!
}

Related

Collectionview rows showing wrongly with JSON data in swift

I am using collectionview in tableview cell
class CategoryNewVC: UIViewController {
#IBOutlet weak var categoryTableview: UITableView!
public var activeCategories : Array<Category_json>?
override func viewDidLoad() {
super.viewDidLoad()
self.activeCategories = homeData?.result?.category_json?.filter({ (item) -> Bool in
return item.status == "A"
})
categoryTableview.reloadData()
}
this is the code for tableview and collectionview
extension CategoryNewVC : UITableViewDelegate,UITableViewDataSource{
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.activeCategories?.count ?? 0
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "CategoryNewTableCell", for: indexPath) as! CategoryNewTableCell
let indexData = self.activeCategories?[indexPath.row]
cell.catNameLbl.text = indexData?.details?.first?.title
cell.activeCategories = self.activeCategories
cell.clcSeller.reloadData()
return cell
}
}
class CategoryNewTableCell: UITableViewCell,UICollectionViewDelegate,UICollectionViewDataSource{
#IBOutlet weak var catNameLbl: UILabel!
#IBOutlet weak var clcSeller: UICollectionView!
public var activeCategories : Array<Category_json>?
override func awakeFromNib() {
super.awakeFromNib()
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return self.activeCategories?[section].sub_categories?.count ?? 0
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "SubCatCollectionCell", for: indexPath) as! SubCatCollectionCell
let activesubCat = self.activeCategories?[indexPath.section].sub_categories
let indexData = activesubCat?[indexPath.item]
cell.lblTitle.text = langType == .en ? indexData?.details?.first?.title : indexData?.details?[1].title
return cell
}
}
with the above code i am getting number of rows for tableview is correct, but in collectionview numberOfItemsInSection coming wrong.. here in every section it showing only first section values in collectionview.. why?
please do help with the code
In the CategoryNewTableCell, you need to make following changes -
public var subCategories : Array<..>? // Array of your subcategories for a particular tableViewCell
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return self.subCategories?.count ?? 0
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "SubCatCollectionCell", for: indexPath) as! SubCatCollectionCell
// Change here
let subCategory = self.subCategories?[indexPath.item]
cell.lblTitle.text = langType == .en ? subCategory?.details?.first?.title : subCategory?.details?[1].title
return cell
}
Finally you need to pass subCategories to your tableViewCell like this - from cellForRow implementation -
cell.subCategories = indexData?.sub_categories

UICollectionViewCell did select item not working

I have an issue with a collectionView inside a TableVieCell. When i tap on a collectionCell, didSelectItemAt doesn´t get called. I have a button in the collectionCell so i tried to disable the user interaction and enable the contentView userInteraction but it didn't work.
The red rectangle is the tableCell and the blue rectangle is the collecionView insede the table view cell
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if let cell = tableView.dequeueReusableCell(withIdentifier: "MedCellWithCollection") as? MedCellWithCollection{
let backgroundView = UIView()
backgroundView.backgroundColor = UIColor.white.withAlphaComponent(0.0)
cell.selectedBackgroundView = backgroundView
cell.setMedName(name: self.medCatalog[indexPath.row].nombre, uso: self.medCatalog[indexPath.row].uso , array: self.medCatalog[indexPath.row].enfermedades[0].aplicaciones , index: indexPath.row)
cell.layoutIfNeeded()
cell.layoutSubviews()
cell.setNeedsUpdateConstraints()
cell.updateConstraintsIfNeeded()
return cell
}
}
return UITableViewCell()
}
The tableCell
class MedCellWithCollection: UITableViewCell {
//Outlets
#IBOutlet weak var medText: UILabel!
#IBOutlet weak var uso: UILabel!
#IBOutlet weak var arrowIcon: UIImageView!
#IBOutlet weak var CollectionView: UICollectionView!
//Variables
var dosesType:[Aplicacion]?
override func awakeFromNib() {
super.awakeFromNib()
self.collectionViewSetUp()
// Initialization code
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
func setMedName(name: String, uso: String, array: [Aplicacion], index: Int){
self.medText.text = name
self.uso.text = uso
self.dosesType = array
self.CollectionView.reloadData()
}
}
extension MedCellWithCollection: UICollectionViewDataSource, UICollectionViewDelegate{
func collectionViewSetUp(){
self.CollectionView.delegate = self
self.CollectionView.dataSource = self
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return self.dosesType?.count ?? 0
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
if let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "doseColletion", for: indexPath as IndexPath) as? DoseCollection {
cell.setButtonConfig(doseType: self.dosesType![indexPath.row].metodo , index: indexPath.row)
return cell
}
return UICollectionViewCell()
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
print("tapped")
}
}
CollectionCell
import UIKit
class DoseCollection: UICollectionViewCell {
//Outlets
#IBOutlet weak var Button: Button!
//Variables
let constants = Constants()
func setButtonConfig(doseType: String, index: Int){
self.Button.titleLabel?.text = doseType
self.Button.backgroundColor = constants.COLOR_ARRAY[index]
}
override func layoutSubviews() {
super.layoutSubviews()
}
override func layoutIfNeeded() {
super.layoutIfNeeded()
}
}
Potential Solutions:
1) Should be Single Selection for tableView selection property, programmatically it can be done by tableView.allowsSelection = true
2) The class is not the UITableViewDelegate for that table view, though UITableViewController is supposed to set that automatically.
tableView?.delegate = self
3) If the problem arise with UITapGestureRecognizer:
let tap = UITapGestureRecognizer(target: self, action:Selector("dismissKeyboard"))
view.addGestureRecognizer(tap)
tap.cancelsTouchesInView = false
BOL :)
In my case, I want to change the background of the button in other words the background of the cell in the collection view:
class CustomCVCell: UICollectionViewCell {
override var isSelected: Bool {
didSet {
grayBackgroundViewWithImage.image =
isSelected ? UIImage(named: "") : UIImage()
}
}
In the main class where the collection view is stored create this variable:
class CustomViewController: UIViewController {
///save the indexPath of last selected cell
private var lastSelectedIndexPath: IndexPath? }
In viewDidLoad() set this value to false:
customCollectionView.allowsMultipleSelection = false
Further code in data source. In my case, the first cell should be is selected:
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: CustomCVCell.cellID(),
for: indexPath) as! CustomCVCell
if indexPath.row == 0 {
lastSelectedIndexPath = indexPath
cell.isSelected = true
}
//update last select state from lastSelectedIndexPath
cell.isSelected = (lastSelectedIndexPath == indexPath)
return cell
}
Further code in the delegate:
///UICollectionViewDelegate
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
guard lastSelectedIndexPath != indexPath else { return }
if let index = lastSelectedIndexPath {
let cell = collectionView.cellForItem(at: index) as! CustomCVCell
cell.isSelected = false
}
let cell = collectionView.cellForItem(at: indexPath) as! CustomCVCell
cell.isSelected = true
lastSelectedIndexPath = indexPath
}

In iOS Swift integrate Different array for CollectionView Inside TableView in Swift 4

How to set CollectionView data to Collection tag.collection tag count is not fixed .How to integarte cellForItemAt and numberOfItemsInSection in CollectionView .So I have a collectionView inside of a tableView. I would like to use the values from my array to populate each labels text inside each collectionViewCell. If I print the code below in collectionView cellForItemAt.
class testViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout {
#IBOutlet weak var providerCategoryTableView: UITableView!
let collectionReuseIdentifier = "selectServiceProviderCollectioncell" // Collection cell identifier in the storyboard
let tableReuseIdentifier = "selectServiceProviderTableViewCell"
var providerCategoryTableViewDictionary = [NSMutableDictionary]()
var providerCategoryCollectionViewDictionary = [String:Any]()
var providerCategoryDictionary = [[String:Any]]()
var ServiceResponse:[[String:Any]] = {[id:1,provider_name:”Telephone”,providers:[{category_name:”Test1”,id:”1”}, {category_name:”Test2”,id:”2”}]], [id:2,provider_name:”MobileNumber”,providers:[{category_name:”Test3”,id:”1”}, {category_name:”Test2”,id:”2”}, {category_name:”Test4”,id:”4”}, {category_name:”Test5”,id:”5”}]]}
var setIndexTag:Int = 0
var cellForItemIndexTag:Int = 0
var exapandTableViewArray = [Int]()
override func viewDidLoad() {
super.viewDidLoad()
initControls()
}
// Expand function
func isExpandable(tableViewHeight:Int) -> Bool {
for item in exapandTableViewArray {
if(tableViewHeight == item){
return true
}
}
return false
}
// MARK: - Private
func initControls(){
providerCategoryTableView.tableFooterView = UIView()
callSelectServiceProvidersAPI()
addServiceProviderLabel.attributedText = GlobalFunctions().addNormalAndBoldText(normalText: NSLocalizedString("RecipientSelectServiceProvidersViewController.addServiceProviderNormalLabel", comment: ""), boldText: NSLocalizedString("RecipientSelectServiceProvidersViewController.addServiceProviderBoldLabel", comment: ""), fontSize : 16.0)
DontSeeYourServiceUILabel.attributedText = GlobalFunctions().addNormalAndBoldText(normalText: NSLocalizedString("RecipientSelectServiceProvidersViewController.DontSeeYourServiceUINormalLabel", comment: ""), boldText: NSLocalizedString("RecipientSelectServiceProvidersViewController.DontSeeYourServiceUIBoldLabel", comment: ""),fontSize : 16.0)
suggestAServiceUIView.layer.borderColor = UIColor( red: CGFloat(115/255.0), green: CGFloat(204/255.0), blue: CGFloat(215/255.0), alpha: CGFloat(1.0) ).cgColor
}
// MARK: - UITableView
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return ServiceResponse.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: tableReuseIdentifier, for: indexPath) as! RecipientSelectServiceProviderTableViewCell
let providerCategoryObject = selectServiceProviderResponse[indexPath.row]
cell.categoryNameLabel.text = (providerCategoryObject["name"] as? String)!
cell.categoryCollectionView.delegate = self
cell.categoryCollectionView.dataSource = self
cell.categoryCollectionView.tag = indexPath.row
cell.categoryCollectionView.reloadData()
return cell
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
if(isExpandable(tableViewHeight:indexPath.row)){
return 60
}else{
return 120
}
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let selectedCell = tableView.cellForRow(at: indexPath) as! RecipientSelectServiceProviderTableViewCell
let UpBlueImage = UIImage(named: "up_blue_arrow")
let UpBlueImageData = UIImagePNGRepresentation(UpBlueImage!)
let SelectedImageData = UIImagePNGRepresentation((selectedCell.UpDownImageView.image)!)
if (SelectedImageData == UpBlueImageData){
exapandTableViewArray.append(indexPath.row)
selectedCell.UpDownImageView.image = UIImage(named:"down_blue_arrow")
self.CategoryTableView.beginUpdates()
self.CategoryTableView.endUpdates()
}else{
if let index = exapandTableViewArray.index(of:indexPath.row) {
exapandTableViewArray.remove(at: index)
}
selectedCell.UpDownImageView.image = UIImage(named:"up_blue_arrow")
self.CategoryTableView.beginUpdates()
self.CategoryTableView.endUpdates()
}
}
// MARK: - UICollectionView
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
//return collectioncategories.count
/* if collectionView.tag == 0{
return collectioncategories.count
}else if collectionView.tag == 1{
return collectionSecondcategories.count
}*/
for obj in ServiceResponse {
if collectionView.tag == setIndexTag {
let providers:[[String: Any]] = obj["providers"] as! [[String : Any]]
return providers.count
}
setIndexTag = setIndexTag + 1
}
return 0
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: collectionReuseIdentifier, for: indexPath) as! RecipientSelectServiceProviderCollectionViewCell
//cell.categoryUILabel.text = collectioncategories[indexPath.row]
/*if collectionView.tag == 0{
cell.categoryUILabel.text = collectioncategories[indexPath.row]
}else if collectionView.tag == 1{
cell.categoryUILabel.text = collectionSecondcategories[indexPath.row]
}*/
for obj in ServiceResponse {
if collectionView.tag == cellForItemIndexTag {
let providers:[[String: Any]] = obj["providers"] as! [[String : Any]]
let data = providers[indexPath.row]
print("providers",providers[indexPath.row])
print("data",data)
for provider in providers {
print("cellForItemAt provider.name",provider["name"] as! String)
cell.categoryUILabel.text! = (provider["name"] as? String)!
print("cell.categoryUILabel.text",cell.categoryUILabel.text!)
}
}
cellForItemIndexTag = cellForItemIndexTag + 1
}
return cell
}
/* func collectionView(_ collectionView: UICollectionView,layout collectionViewLayout: UICollectionViewLayout,sizeForItemAt indexPath: IndexPath) -> CGSize {
let nbCol = 3
let flowLayout = collectionViewLayout as! UICollectionViewFlowLayout
let totalSpace = flowLayout.sectionInset.left + flowLayout.sectionInset.right + (flowLayout.minimumInteritemSpacing * CGFloat(nbCol - 1))
let size = Int((collectionView.bounds.width - totalSpace) / CGFloat(nbCol))
return CGSize(width: size, height: size)
}*/
I want
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
//return collectioncategories.count
if collectionView.tag == 0{
return collectioncategories.count
}else if collectionView.tag == 1{
return collectionSecondcategories.count
}
}
But 0,1....n collectionView.tag not fixed and inside array count also different.Please Its Urgent.Thanks
i have done a similar application where what we did is create one parent array
ie
var tableViewDataArray = [HomeDataHolder] () // which includes the type , sub category in my case myclass contains category name , category id and product array
after this add each category in to this array for me, added dataArry[banners,toppicks,.....]
this is how added class object to arraya
if let categoryes = JSON["categories"] as? NSArray{
for index in 0..<categoryes.count{
self.categoryArray.add(categoryes[index])
}
print(self.categoryArray)
self.session.saveCategory(self.categoryArray)
let catObject = HomeDataHolder(type:"CATEGORY").addCategoryes(categoryArray: self.categoryArray)
self.tableViewDataArray.append(catObject)
}
set tableview datasource as this array
if you need different type design design different cells
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let homeData = tableViewDataArray[indexPath.row] as! HomeDataHolder
if homeData.type == "CATEGORY"{
let cell = tableView.dequeueReusableCell(withIdentifier: "category_name_cell", for: indexPath) as! HomeCategoryTableViewCell
cell.selectionStyle = .none
let dataArray = homeData.dataArray
cell.setProducArray(dataArray!)
cell.delegate = self
return cell
}else if .......
in my HomeCategoryTableViewCell class
func setProducArray(_ data:NSMutableArray){
for index in 0..<data.count{
dataArray.add(data[index])
}
colectionView.reloadData()
}
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return dataArray.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "home_categoryes_cellection_cell", for: indexPath) as! HomeCategoriesCollectionViewCell
if let dataDictionary = dataArray[indexPath.row] as? NSDictionary{
utility.setCornerRadius([cell.containerView], cornerRadies: 19)
cell.categoryNameLabel.text = dataDictionary.getStringValue("name")
print(dataDictionary.getStringValue("name"))
}
return cell
}
and my HomeCategoryTableViewCell contains a collection view cell.setProducArray(dataArray!) will change the datasource of the collectionview
In your cellForRow of the TableView access the collectionView with viewWithTag and then give it the indexPath.row in the accessiblityHint property and call reload. Then in the your numberOfSections, numberOfItems or cellForItem methods of collectionView you can access the accessiblityHint property and access your array's index to display the data you want.

Two Collection Views in One View Controller iOS

I have two collection Views in One View Controller, First Collection View have class CollectionCellA with imageA as UIImageView! and labelA as UILabel!. Similarly Second Collection View with class CollectionCellB with imageB and labelB. I tried to run with following swift code but it show just blank(white) screen.
class ViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource {
var imageArroy = [UIImage(named: "1"), UIImage(named: "2"), UIImage(named: "3"), UIImage(named: "5"), UIImage(named: "6")]
var imageArroyB = [UIImage(named: "a"), UIImage(named: "b"), UIImage(named: "c"), UIImage(named: "d"), UIImage(named: "e")]
var labelA: ["Electronics", "Cars", "Pets", "Mobiles", "Food"]
var labelB: ["UK", "Ireland", "India", "Germany", "Other EU"]
#IBOutlet weak var CollectionViewA: UICollectionView!
#IBOutlet weak var CollectionViewB: UICollectionView!
override func viewDidLoad() {
super.viewDidLoad()
CollectionViewA.delegate = self
CollectionViewB.delegate = self
CollectionViewA.dataSource = self
CollectionViewB.dataSource = self
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
if collectionView == self.CollectionViewA {
return 0 // Replace with count of your data for collectionViewA
}
return 0
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
if collectionView == self.CollectionViewA {
let cellA = collectionView.dequeueReusableCell(withReuseIdentifier: "CollectionCellA", for: indexPath) as! CollectionCellA
// Set up cell
return cellA
}
else {
let cellB = collectionView.dequeueReusableCell(withReuseIdentifier: "CollectionCellB", for: indexPath) as! CollectionCellB
// ...Set up cell
return cellB
}
}
This code works for Two Collection View in One View Controller with images and label.
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
if collectionView == self.CollectionViewA {
return imageArroy.count
}
return imageArroyB.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
if collectionView == self.CollectionViewA {
let cellA = collectionView.dequeueReusableCell(withReuseIdentifier: "CollectionCellA", for: indexPath) as! CollectionCellA
cellA.imageA.image = imageArroyB[indexPath.row]
cellA.labelA.text = labelA[indexPath.row]
// Set up cell
return cellA
}
else {
let cellB = collectionView.dequeueReusableCell(withReuseIdentifier: "CollectionCellB", for: indexPath) as! CollectionCellB
cellB.imageB.image = imageArroyB[indexPath.row]
cellB.labelB.text = labelB[indexPath.row]
// ...Set up cell
return cellB
}
}
For me below code works like a charm . you should send/assign value in cellForItemAt indexPath
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
if collectionView == self.CollectionViewA {
return imageArroy.count
}
return imageArroyB.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
if collectionView == self.CollectionViewA {
let cellA = collectionView.dequeueReusableCell(withReuseIdentifier: "CollectionCellA", for: indexPath) as! CollectionCellA
// Set up cell
cellA.lbl.text = labelA[indexPath.row]
return cellA
}
else {
let cellB = collectionView.dequeueReusableCell(withReuseIdentifier: "CollectionCellB", for: indexPath) as! CollectionCellB
// ...Set up cell
cellB.lbl.text = labelB[indexPath.row]
return cellB
}
}
}
class CollectionCellA : UICollectionViewCell {
#IBOutlet weak var lbl: UILabel!
}
class CollectionCellB : UICollectionViewCell {
#IBOutlet weak var lbl: UILabel!
}
Add two collection view and connect delegate and data source with view countroller,create collection view cell and connect with cell and outlets
#IBOutlet weak var collectionView2: UICollectionView!
#IBOutlet weak var collectionview1: UICollectionView!
var days = ["Sun","Mon","Tues","Wed","Thur","Frid","Sat"]
var dayTask = [String]()
var task = [["Sun1","Mon1","Tues1","Wed1","Thur1","Frid1","Sat1"],["Sun2","Mon2","Tue2","Wed2"],["Sun3","Mon3","Tues3","Wed3","Thur3","Frid3","Sat3"],["Sun4","Mon4"],["Sun5","Mon5","Tues5","Wed5","Thur5","Frid5","Sat5"],["Sun6","Mon6","Tues6","Wed6"],["Sun7","Mon7","Tues7","Wed7","Thur7"]]
override func viewDidLoad() {
super.viewDidLoad()
dayTask = task[0]
// Do any additional setup after loading the view.
}
Collection view data source and delgate
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
if collectionView == collectionview1{
return days.count
}else{
return dayTask.count
}
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CollectionViewCell1", for: indexPath) as! CollectionViewCell1
if collectionView == collectionview1{
cell.label.text = days[indexPath.row]
let collectionViewLayout = collectionView.collectionViewLayout as? UICollectionViewFlowLayout
collectionViewLayout?.sectionInset = UIEdgeInsets(top: 0, left: 20, bottom: 0, right: 40)
collectionViewLayout?.invalidateLayout()
}else
{
let collectionViewLayout = collectionView.collectionViewLayout as? UICollectionViewFlowLayout
collectionViewLayout?.sectionInset = UIEdgeInsets(top: 10, left: 20, bottom: 0, right: 40)
collectionViewLayout?.invalidateLayout()
cell.label.text = dayTask[indexPath.row]
}
return cell
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
if collectionView == collectionview1{
dayTask = task[indexPath.row]
collectionView2.reloadData()
}
}

Pass data from collectionCell inside tableCell to secondVC use protocol

I have two viewController's. The first VC has collectionCell inside tableCell. The second VC has collectionCell, and I have swift File with Model have a class. I need to pass data from the first VC (collectionCell) to the second VC.
Pass data need from collectionCell because collectionCell has images (from swift File - Model). I think need use a protocol, but I don't really understand how to work with a protocol. Please help.
My code:
1stVC(viewController):
class ViewController1: UIViewController {
#IBOutlet weak var tableView: UITableView!
var image: [Model] = []
var ref: FIRDatabaseReference!
override func viewDidLoad() {
super.viewDidLoad()
ref = FIRDatabase.database().reference(withPath: "Студии2")
ref.observe(.value, with: { (snapshot) in
var newImages: [Model] = []
for item in snapshot.children {
let object = Model(snapshot: item as! FIRDataSnapshot)
newImages.append(object)
}
self.image = newImages
self.tableView.reloadData()
})
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}
extension ViewController1: UITableViewDelegate, UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return image.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! TableViewCell1
cell.images = [image[indexPath.row].image,
image[indexPath.row].image2]
return cell
}
}
1stVC(collectionCell inside tableCell):
protocol PostDelegate {
func selectedPost(cell: String)
}
class TableViewCell1: UITableViewCell {
var images = [String]()
var selecetdItem: Model?
var postDelegate: PostDelegate?
}
extension TableViewCell1: UICollectionViewDelegate, UICollectionViewDataSource {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return images.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! CollectionViewCell1
cell.imagesView.sd_setImage(with: URL(string: images[indexPath.item]))
return cell
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
postDelegate?.selectedPost(cell: self.images[indexPath.item])
print(images[indexPath.item])
}
}
2ndVC(viewController):
class ViewController3: UIViewController {
#IBOutlet weak var collectionView: UICollectionView!
// var images = [String]()
var images: [Model] = []
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}
extension ViewController3: UICollectionViewDelegate, UICollectionViewDataSource {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return images.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! CollectionViewCell3
// let array = [images[indexPath.item].images,
// images[indexPath.item].images2]
// cell.imagesView.sd_setImage(with: URL(string: array[indexPath.item]))
// cell.imagesView.sd_setImage(with: URL(string: images[indexPath.item]))
return cell
}
}
Model(swift File have a class):
class Model {
var image: String!
var image2: String!
var images: [String] = []
var images2: [String] = []
var ref: FIRDatabaseReference!
init(snapshot: FIRDataSnapshot) {
ref = snapshot.ref
let value = snapshot.value as! NSDictionary
let snap1 = value["hall1"] as? NSDictionary
let snap2 = value["hall2"] as? NSDictionary
image = snap1?["qwerty"] as? String ?? ""
image2 = snap2?["qwerty"] as? String ?? ""
if let post1 = snap1 as? [String: AnyObject] {
for (_, value) in post1["images"] as! [String: AnyObject] {
self.images.append(value as! String)
}
}
if let post1 = snap1 as? [String: AnyObject] {
for (_, value) in post1["images"] as! [String: AnyObject] {
self.images2.append(value as! String)
}
}
}
}
Pass ViewController1 as the postDelegate of TableViewCell1
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! TableViewCell1
//make VC1 as post delegate of cell
(cell as! TableViewCell1).postDelegate = self
cell.images = [image[indexPath.row].image,
image[indexPath.row].image2]
return cell
}
Finally implement
extension ViewController1 : PostDelegate {
func selectedPost(cell: String) {
//call self.perform segue or load VC2 and pass data here
}
}
Pinch of Advice :
var postDelegate: PostDelegate?
will result in strongly holding a reference to the delegate being passed. Which will result in memory leaks. To make it safer declare delegate as weak
weak var postDelegate: PostDelegate?
In order to make the Protocol weak your protocol
protocol PostDelegate: NSObjectProtocol {
func selectedPost(cell: String)
}

Resources