Display different arrays in collectionView after click on different rows in tableView - ios

In my viewController i have tableView and collectionView.
And i try to display different arrays in collectionView when i click on different rows in tableView.
So when i click on firstRow in tableView, i want to display firstArray in collectionView, when i click on secondRow in tableView, i want to display secondArray in collectionView and when i click on thirdRow in tableView, i want to display thirdArray in collectionView.
How can i do this?
My test code:
class ViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var collectionView: UICollectionView!
#IBOutlet weak var tableView: UITableView!
var tableArray: [String] = ["1", "2", "3"]
var secondArray: [String] = ["One", "Two"]
var thirdArray: [String] = ["Three", "Four"]
var fourthArray: [String] = ["Five", "Six"]
// TABLEVIEW
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return tableArray.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "tableCell", for: indexPath) as! TableCell
cell.tableLabel.text = tableArray[indexPath.row]
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
print(indexPath)
}
// COLLECTIONVIEW
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return secondArray.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "collectionCell", for: indexPath) as! CollectionCell
cell.collectionLabel.text = secondArray[indexPath.item]
return cell
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
print(indexPath)
}
}
class TableCell: UITableViewCell {
#IBOutlet weak var tableLabel: UILabel!
}
class CollectionCell: UICollectionViewCell {
#IBOutlet weak var collectionLabel: UILabel!
}
I understand what need to use condition if, but how to use correct it?

You may add your arrays inside a dictionary (collectionData) using the index as key, in this way their lookup is totally dynamic and you don't need any if then else, so your code might be:
class ViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var collectionView: UICollectionView!
#IBOutlet weak var tableView: UITableView!
var tableArray: [String] = ["1", "2", "3"]
// you may want to feed the dictionary directly with the arrays (feel free to remove them)
var collectionData: [Int: [String]] = [:]
var secondArray: [String] = ["One", "Two"]
var thirdArray: [String] = ["Three", "Four"]
var fourthArray: [String] = ["Five", "Six"]
override func viewDidLoad() {
super.viewDidLoad()
self.collectionData[0] = secondArray
self.collectionData[1] = thirdArray
self.collectionData[2] = fourthArray
}
func getCurrentArray() -> [String]? {
let currentRow = self.tableView.indexPathForSelectedRow?.row ?? 0
let array = self.collectionData[currentRow]
return array
}
// TABLEVIEW
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return tableArray.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "tableCell", for: indexPath) as! TableCell
cell.tableLabel.text = tableArray[indexPath.row]
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
self.collectionView.reloadData()
}
// COLLECTIONVIEW
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return self.getCurrentArray()?.count ?? 0
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "collectionCell", for: indexPath) as! CollectionCell
cell.collectionLabel.text = self.getCurrentArray()?[indexPath.item]
return cell
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
print(indexPath)
}
}
class TableCell: UITableViewCell {
#IBOutlet weak var tableLabel: UILabel!
}
class CollectionCell: UICollectionViewCell {
#IBOutlet weak var collectionLabel: UILabel!
}

You can create a dictionary and use it. And with the help of key you can easily fetch the different data from different table view cell.

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

Custom Layout UICollectionView

How do I set a horizontal orientation to a collection view in Swift? I need want the row layout to be like the picture below.
#IBOutlet weak var collectionView: UICollectionView!
let cellIdentifier = "cellViewID"
let objects = ["Cat", "Dog", "Fish"]
let images_array = ["break_down_grey", "break_down_grey", "Fish"]
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return objects.count;
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellIdentifier, for: indexPath) as! CustomCollectionViewCell
cell.title.text=objects[indexPath.row]
cell.imageView.image = UIImage(named: images_array[indexPath.row])
print(cell)
return cell
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
print("Cell \(indexPath.row) selected")
}
import UIKit
class CustomCollectionViewCell: UICollectionViewCell {
#IBOutlet weak var imageView: UIImageView!
#IBOutlet weak var title: UILabel!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
}

UITableView in UICollectionView

I placed a tableView inside a collectionView and added the delegates. The problem is, that I want to control the data in the different tableViews in the collectionView.
Every collectionView holds a label with the name of the current day (e.g.: "Monday"). Below the label is a tableView. In the tableView should be displayed different data, based on the index of the collectionView.
In my example, every tableView has two cells. The tableView in the first item of the collectionView should display: cell1: "1" and cell2: "2", the tableView in the second item should display: cell1: "3" and cell2: "4".
I'm currently using the code below:
import UIKit
class StundenplanCollectionViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate, UITableViewDataSource, UITableViewDelegate {
override func viewDidLoad() {
super.viewDidLoad()
myHours.append(myH0)
myHours.append(myH1)
myHours.append(myH2)
myHours.append(myH3)
myHours.append(myH4)
myHours.append(myH5)
collectionView.delegate = self
collectionView.dataSource = self
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
//MARK: Outlets
#IBOutlet weak var collectionView: UICollectionView!
//MARK: Variables
var myDays = ["Montag", "Dienstag", "Mittwoch", "Donnerstag", "Freitag"]
var myHours: [[String]] = Array() //Array that holds myH1 - myH5
var myH0 = ["1", "2"]
var myH1 = ["3", "4"]
var myH2 = ["5", "6"]
var myH3 = ["7", "8"]
var myH4 = ["9", "10"]
var myH5 = ["Error", "Error"]
var tableLoop = 0
var headerColor: UIColor = UIColor( red: CGFloat(255/255.0), green: CGFloat(140/255.0), blue: CGFloat(60/255.0), alpha: CGFloat(1.0))
//MARK: Table and Collection View
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return myDays.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell: StundenplanCollectionViewCell = collectionView.dequeueReusableCell(withReuseIdentifier: "stundenplanCollectionCell", for: indexPath) as! StundenplanCollectionViewCell
cell.titleLabel.text = myDays[indexPath.row]
cell.titleLabel.backgroundColor = headerColor
cell.titleLabel.textColor = UIColor.white
return cell
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return myHours[tableLoop].count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell: StundenplanTableViewCell = tableView.dequeueReusableCell(withIdentifier: "stundenplanTableCell", for: indexPath) as! StundenplanTableViewCell
cell.titleLabel.text = myHours[/*Here should the indexPath.row of the collectionView item be placed*/][indexPath.row]
return cell
}
}
class StundenplanCollectionViewCell: UICollectionViewCell {
#IBOutlet weak var titleLabel: UILabel!
#IBOutlet weak var tableView: UITableView!
}
class StundenplanTableViewCell: UITableViewCell {
#IBOutlet weak var titleLabel: UILabel!
}
Image 1: Here you can see the first tableView in the collectionView (first item of collectionView):
Image 2: Here you can see the second tableView in the collectionView (second Item of collectionView):
Image 3: Storyboard:
Image 4: Structure of the different objects in the view:
Updated code (according to the answer by #missionMan - Thanks by the way!):
import UIKit
class StundenplanCollectionViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate {
override func viewDidLoad() {
super.viewDidLoad()
navigationController?.navigationBar.prefersLargeTitles = false
navigationController?.navigationBar.prefersLargeTitles = true
navigationItem.largeTitleDisplayMode = .always
myHours.append(myH0)
myHours.append(myH1)
myHours.append(myH2)
myHours.append(myH3)
myHours.append(myH4)
myHours.append(myH5)
collectionView.delegate = self
collectionView.dataSource = self
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
//MARK: Outlets
#IBOutlet weak var collectionView: UICollectionView!
//MARK: Variables
var myDays = ["Montag", "Dienstag", "Mittwoch", "Donnerstag", "Freitag"]
var myHours: [[String]] = Array() //Array that holds myH1 - myH5
var myH0 = ["1", "2"]
var myH1 = ["3", "4"]
var myH2 = ["5", "6"]
var myH3 = ["7", "8"]
var myH4 = ["9", "10"]
var myH5 = ["Error", "Error"]
var headerColor: UIColor = UIColor( red: CGFloat(255/255.0), green: CGFloat(140/255.0), blue: CGFloat(60/255.0), alpha: CGFloat(1.0))
//MARK: Table and Collection View
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return myDays.count
}
public func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: "stundenplanCollectionViewCell") as? StundenplanCollectionViewCell else { //how can I access the inner tableView? Error: Use of unresolved identifier 'tableView'
return UICollectionViewCell()
}
//set data and reload inner table from outer view controller (StundenplanCollectionViewController according to your code)
cell.dayItems = myHours[indexPath.row]
cell.tableView.reloadData()
//...
return cell
}
class StundenplanCollectionViewCell: UICollectionViewCell {
#IBOutlet weak var titleLabel: UILabel!
#IBOutlet weak var tableView: UITableView!
var dayItems: [String] = []
override func awakeFromNib() {
super.awakeFromNib()
self.tableView.delegate = self // <-- set delegates inner table
self.tableView.dataSource = self
}
}
extension StundenplanCollectionViewCell: UITableViewDataSource, UITableViewDelegate {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return dayItems.count
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 100
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell: StundenplanTableViewCell = (tableView.dequeueReusableCell(withIdentifier: "stundenplanTableViewCell") as? StundenplanTableViewCell)!
//...
return cell
}
}
class StundenplanTableViewCell: UITableViewCell {
#IBOutlet weak var titleLabel: UILabel!
}
You can add table delegate methods in table cell class
and then you can set data for one day. So each collection cell will have its own table and its own data.
like this:
class StundenplanCollectionViewCell: UICollectionViewCell { //<-- outer cell
#IBOutlet weak var titleLabel: UILabel!
#IBOutlet weak var innerTableView: UITableView! //<-- declare inner table
var dayItems: [String] = []
override func awakeFromNib() {
super.awakeFromNib()
self.innerTableView.delegate = self // <-- set delegates inner table
self.innerTableView.dataSource = self
}
}
extension StundenplanCollectionViewCell: UITableViewDataSource, UITableViewDelegate {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return dayItems.count
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
...
}
...
set data from outer cell of your collectionView in StundenplanCollectionViewController
public func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
guard let cell = collectionView.dequeueReusableCell(withIdentifier: "stundenplanCollectionViewCell") as? StundenplanCollectionViewCell else { //<-- HERE
return UICollectionViewCell()
}
//set data and reload inner table from outer view controller (StundenplanCollectionViewController according to your code)
cell.dayItems = myH[indexPath.row]
cell.innerTableView.reloadData()
...
return cell
}
Why are you trying to dequeue a UICollectionViewCell from a UITableView?
public func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier(reuseIdentifier, forIndexPath: indexPath)
...
}

Clicking the photo then photo goes to detailViewController with Labels at the tableView

What I want to happen is, when I click the photos from the ViewController it will automatically go to the DetailViewController with the labels at the tableViewController below, and the data from the DataSource. and How do I use the Image title as a String in my tableView.
This
Codes from DataSource
import UIKit
class DataSource: NSObject, UICollectionViewDataSource, UICollectionViewDelegate {
var carsToDisplay: [Car] = []
var image : ImageCollectionViewCell!
var views: ViewController!
override init() {
super.init()
//This is the Data I want to show up at my tableView
carsToDisplay = [Car(name: "Tim", price: 123, image: UIImage(named: "1")),Car(name: "T9m", price: 123, image: UIImage(named: "2"))]
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return carsToDisplay.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) as! ImageCollectionViewCell
let car = carsToDisplay[indexPath.item]
cell.imageView.image = car.image
return cell
}
}
Codes from my DetailViewController
import UIKit
class DetailViewController: UIViewController, UICollectionViewDataSource, UITableViewDataSource {
#IBOutlet weak var collectionView: UICollectionView!
#IBOutlet weak var tableView: UITableView!
var savedImage : [Car] = []
var carsToDisplay: [Car] = []
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return carsToDisplay.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
//How do I put the Image title as a String?
let car = carsToDisplay[indexPath.item]
cell.textLabel?.text = car.name!
return cell
}
}

UITableView dataSource from Class object within a UICollectionViewCell

I would like to see each allItems for each object in inventory to be displayed in each row. As it is now, where I have written indexPathOfCollectionView, there's a 0 to see that it is actually working, but I don't know which variable should I write to be able to see each allItems from the inventory.
var inventory = [Item]()
class Item {
var name: String!
var allItems: [String]!
init(name: String, allItems: [String]) {
self.name = name
self.allItems = allItems
}
}
Collection Cell:
class ItemCollectionViewCell: UICollectionViewCell, UITableViewDelegate, UITableViewDataSource {
var inventory = [Item]()
#IBOutlet weak var testTableView: UITableView!
#IBOutlet weak var nameLabel: UILabel!
func configureCell(_ inventory: Item) {
nameLabel.text = inventory[indexPath.row]
testTableView.dataSource = self
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return inventory[indexPathOfCollectionView*].allItems.count
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
var cell: UITableViewCell? = tableView.dequeueReusableCell(withIdentifier: "ItemsCell")
if(cell == nil){
cell = UITableViewCell(style: UITableViewCellStyle.default, reuseIdentifier: "ItemsCell")
}
cell.textLabel?.text = inventory[indexPathOfCollection*].allItems[indexPath.row]
return cell
}
}
This is in the viewController
class VC: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return inventory.count
}
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CollectionCellItem", for: indexPath) as! ItemCollectionViewCell
let it: Item!
it = inventory[indexPath.row]
cell.configureCell(it)
return cell
}
}
Here is a screenshot of what I've got
From what I can tell, from your class Item remove the Inventory array as it is not needed inside your model. It should be present with the UIViewController. Making the following changes ought to make your code run as required!
Change your UIViewController to-
class VC: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource {
var inventory = [Item]()
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return inventory.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CollectionCellItem", for: indexPath) as! ItemCollectionViewCell
//Just pass the model inside of the array!
cell.itemsList = inventory[indexPath.item]
cell.configureCell()
return cell
}
}
And inside your UICollectionViewCell:
class ItemCollectionViewCell: UICollectionViewCell, UITableViewDelegate, UITableViewDataSource {
var itemsList : Item!
#IBOutlet weak var testTableView: UITableView!
#IBOutlet weak var nameLabel: UILabel!
override func awakeFromNib() {
super.awakeFromNib()
testTableView.dataSource = self
}
func configureCell() {
testTableView.reloadData()
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return itemsList.allItems.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
var cell: UITableViewCell? = tableView.dequeueReusableCell(withIdentifier: "ItemsCell")
if(cell == nil){
cell = UITableViewCell(style: UITableViewCellStyle.default, reuseIdentifier: "ItemsCell")
}
//get array of strings from inside that particular model!
cell.textLabel?.text = itemsList.allItems[indexPath.row]
return cell
}
}

Resources