Collectionview rows showing wrongly with JSON data in swift - ios

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

Related

How can I figure out which tableView Cell is selected when collectionview is scrolled horizontally

I have collectionView inside TableViewCell.
TableView has 1 section and 4 rows.
I want to figure out which row of tableviewcell is selected when collectionView is Scrolled Horizontally.
I tryed to figure out by putting tableView row in "var nowRow" variable like below code. But It does not work.
How can I find out which row of tableviewcell is selected?
class Home2ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate, UICollectionViewDataSource, UICollectionViewDelegate {
var posts = [Post]()
var nowRow = Int()
override func viewDidLoad() {
// get posts elements here
//posts.append(element).......
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return posts.count // 4counts
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
// let cell = DetailMutiTableViewCell()
let cell = tableView.dequeueReusableCell(withIdentifier: "DetailMutiTableViewCell", for: indexPath) as! DetailMutiTableViewCell
nowRow = indexPath.row
cell.post = posts[nowRow]
cell.collectionView1.delegate = self
cell.collectionView1.dataSource = self
cell.collectionView1.reloadData()
return cell
}
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return posts[nowRow].imageUrls.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "MultiImagesCollectionViewCell", for: indexPath) as! MultiImagesCollectionViewCell
let photoUrlString = posts[nowRow].imageUrls[indexPath.item] // ←error occured
let photoUrl = URL(string: photoUrlString)
cell.imageView1.sd_setImage(with: photoUrl)
return cell
}
}
editeditedit
As you have no doubt discovered, interacting with the collectionViews in your table rows does not trigger the tableView method tableView(_:didSelectRowAt:), and tableView.indexPathForSelectedRow is nil because no row has been selected. You need a way to map from the collectionView to the indexPath.row that contains it. This information is known at tableViewCell setup time.
Add a dictionary to your Home2ViewController that maps a UICollectionView to a row Int:
var collectionViewRow = [UICollectionView : Int]()
Add the entries in tableView(_:cellForRowAt:) where you know the row and collectionView:
collectionViewRow[cell.collectionView1] = indexPath.row
Then, anytime you have a collectionView, you can look up its row:
let row = collectionViewRow[collectionView]!
Here's the whole code:
class Home2ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate, UICollectionViewDataSource, UICollectionViewDelegate {
var posts = [Post]()
var collectionViewRow = [UICollectionView : Int]()
override func viewDidLoad() {
// get posts elements here
//posts.append(element).......
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return posts.count // 4counts
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
// let cell = DetailMutiTableViewCell()
let cell = tableView.dequeueReusableCell(withIdentifier: "DetailMutiTableViewCell", for: indexPath) as! DetailMutiTableViewCell
collectionViewRow[cell.collectionView1] = indexPath.row
cell.post = posts[indexPath.row]
cell.collectionView1.delegate = self
cell.collectionView1.dataSource = self
cell.collectionView1.reloadData()
return cell
}
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
let row = collectionViewRow[collectionView]!
return posts[row].imageUrls.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "MultiImagesCollectionViewCell", for: indexPath) as! MultiImagesCollectionViewCell
let row = collectionViewRow[collectionView]!
let photoUrlString = posts[row].imageUrls[indexPath.item] // ←error occured
let photoUrl = URL(string: photoUrlString)
cell.imageView1.sd_setImage(with: photoUrl)
return cell
}
}
Notes:
The force unwrap of the dictionary lookup won't fail because the collectionView will be in there. If you want to unwrap it with if let, you'll need to decide what to do when you don't get a row (which shouldn't happen).
This method could fail if your table allows editing (user can rearrange order of rows or delete rows). If you don't support editing, then this will work fine. To support editing, you could change the dictionary to [UICollectionView : UITableViewCell]. Then, given a UICollectionView, you could look up its cell, and then call let indexPath = tableView.indexPath(for: cell) to get the indexPath and your row is then just indexPath.row.

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

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.

Segue in a UICollectionView embedded in a UITableviewCell, Swift

I have made a UICollectionView inside a UITableViewCell and it works pretty Fine. My only Problem is, that I can't perform a Segue on didSelectItemAt Method to another ViewController.
I know I have to perform it from the TableViewController,I made a segue on the Storyboard and I tried multiple possibilities but for some reasons it doesn't work.
Here my TableviewController:
import UIKit
import RealmSwift
import SwiftyJSON
class HomeVTwoTableViewController: UITableViewController {
let realm = try! Realm()
let headers = ["1","2","3"]
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewWillAppear(_ animated: Bool) {
self.tableView.separatorStyle = .none
}
//MARK: Custom Tableview Headers
override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return headers[section]
}
//MARK: DataSource Methods
override func numberOfSections(in tableView: UITableView) -> Int {
return headers.count
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1
}
//Choosing the responsible PrototypCell for the Sections
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.section == 0 {
let cell = tableView.dequeueReusableCell(withIdentifier: "cellBig", for: indexPath) as! HomeVTwoTableViewCell
cell.update()
return cell
} else {
return UITableViewCell()
}
}
// This on of my tries to perform a segue
func liveCellSelected() {
performSegue(withIdentifier: "showChat", sender: nil)
}
}
And here my TableViewCell with the embedded CollectionView:
import UIKit
import RealmSwift
class HomeVTwoTableViewCell: UITableViewCell{
var liveCommunities: Results<Community>?
#IBOutlet weak var collectionView: UICollectionView!
override func awakeFromNib() {
super.awakeFromNib()
collectionView.delegate = self
collectionView.dataSource = self
}
}
extension HomeVTwoTableViewCell:
UICollectionViewDataSource,UICollectionViewDelegate {
func numberOfSections(in collectionView: UICollectionView) -> Int
{
return 1
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int
{
return(liveCommunities?.count)!
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell
{
guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "collectionCellBig", for: indexPath) as? HomeVTwoCollectionViewCell else
{
fatalError("Cell has wrong type")
}
//removes the old image
cell.imageView.image = UIImage(named: "No Image")
cell.titleLbl.text = nil
//set url and Picture
url = (liveCommunities?[indexPath.row].pictureId)!
let name : String = (liveCommunities?[indexPath.row].communityName)!
let channelName : String = (liveCommunities?[indexPath.row].channelName)!
cell.titleLbl.text = name
cell.senderLbl.text = channelName
cell.imageView.downloadedFrom(link :"someSecretUrl")
return cell
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
selectedCommunity = (liveCommunities?[indexPath.row].communityId)!
HomeVTwoTableViewController().liveCellSelected()
}
}
I found another question with a similar theme, but couldn't implement a delegate Protocol without creating problems with the already existing delegates.
Maybe it`s an obvious mistake but I can't see it.
Thanks in advance.
You're instantiating a new instacne of your home controller with this:
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
selectedCommunity = (liveCommunities?[indexPath.row].communityId)!
HomeVTwoTableViewController().liveCellSelected()
}
what you should do is to make it via a delegate, or you move your collectionview delegate to the main controller
protocol CellCollectionViewDelegate: class{
func didselect()
}
and you implement the delegate in cell and your home controller
May be you can create a variable to handle this. You can do optional also.
class HomeVTwoTableViewCell: UITableViewCell{
var liveCommunities: Results<Community>?
#IBOutlet weak var collectionView: UICollectionView!
var didSelectAction: () -> Void // add your action here
Here you can call to this function
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
selectedCommunity = (liveCommunities?[indexPath.row].communityId)!
HomeVTwoTableViewController().liveCellSelected()
didSelectAction() // Invoque your action
}
//On the cell creator, add the navigation or logic when you want to tap the cell
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.section == 0 {
let cell = tableView.dequeueReusableCell(withIdentifier: "cellBig", for: indexPath) as! HomeVTwoTableViewCell
cell.update()
cell.didSelectAction = {
// add here your navigation
}
return cell
} else {
return UITableViewCell()
}
}
Ok as it seems there are two Solutions to this Problem.
One is via a Variable and one via a delegate. As I know the delegate one is more common.
Solution 1 with Variable:
Here my TableviewController:
import UIKit
class TableViewController: UITableViewController {
let headers = ["1","2","3"]
override func viewDidLoad() {
super.viewDidLoad()
}
override func numberOfSections(in tableView: UITableView) -> Int {
return headers.count
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cellBig", for: indexPath) as! HomeVTwoTableViewCell
//Fill function, insert Navigation
cell.didSelectAction = {
self.performSegue(withIdentifier: "testSegue", sender: nil)
}
return cell
}
And here my TableViewCell with the embedded CollectionView:
import UIKit
class HomeVTwoTableViewCell: UITableViewCell{
var liveCommunities: Results<Community>?
//Instantiate function
var didSelectAction: () -> Void = {}
#IBOutlet weak var collectionView: UICollectionView!
override func awakeFromNib() {
super.awakeFromNib()
collectionView.delegate = self
collectionView.dataSource = self
}
}
extension HomeVTwoTableViewCell:
UICollectionViewDataSource,UICollectionViewDelegate {
func numberOfSections(in collectionView: UICollectionView) -> Int
{
return 1
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int
{
return(liveCommunities?.count)!
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell
{
guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "collectionCellBig", for: indexPath) as? HomeVTwoCollectionViewCell else
{
fatalError("Cell has wrong type")
}
//removes the old text
cell.titleLbl.text = nil
cell.senderLbl.text = nil
let name : String = (liveCommunities?[indexPath.row].communityName)!
let channelName : String = (liveCommunities?[indexPath.row].channelName)!
cell.titleLbl.text = name
cell.senderLbl.text = channelName
return cell
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
selectedCommunity = (liveCommunities?[indexPath.row].communityId)!
// Invoque your action
didSelectAction()
}
}
Solution 2 with Delegate and Protocol:
Here my TableviewController:
import UIKit
class TableViewController: UITableViewController {
let headers = ["1","2","3"]
override func viewDidLoad() {
super.viewDidLoad()
}
override func numberOfSections(in tableView: UITableView) -> Int {
return headers.count
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cellBig", for: indexPath) as! HomeVTwoTableViewCell
//Add delegate
cell.delegate = self
return cell
}
//Add Extension with Navigation
extension HomeVTwoTableViewController: CellCollectionViewDelegate {
func didSelect() {
performSegue(withIdentifier: "showChat", sender: nil)
}
}
And here my TableViewCell with the embedded CollectionView:
import UIKit
//Create a delegate protocol
protocol CellCollectionViewDelegate: class{
func didSelect()
}
class HomeVTwoTableViewCell: UITableViewCell{
var liveCommunities: Results<Community>?
//Add a delegate property
weak var delegate: CellCollectionViewDelegate?
#IBOutlet weak var collectionView: UICollectionView!
override func awakeFromNib() {
super.awakeFromNib()
collectionView.delegate = self
collectionView.dataSource = self
}
}
//Adopt and implement the Delegate Protocol
extension HomeVTwoTableViewCell:
UICollectionViewDataSource,UICollectionViewDelegate {
func numberOfSections(in collectionView: UICollectionView) -> Int
{
return 1
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int
{
return(liveCommunities?.count)!
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell
{
guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "collectionCellBig", for: indexPath) as? HomeVTwoCollectionViewCell else
{
fatalError("Cell has wrong type")
}
//removes the old text
cell.titleLbl.text = nil
cell.senderLbl.text = nil
let name : String = (liveCommunities?[indexPath.row].communityName)!
let channelName : String = (liveCommunities?[indexPath.row].channelName)!
cell.titleLbl.text = name
cell.senderLbl.text = channelName
return cell
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
selectedCommunity = (liveCommunities?[indexPath.row].communityId)!
//call delegate method
delegate?.didSelect()
}
}
I tried to sum up the Solutions from
Abdoelrhman Mohamed and Alexkater and write it out in detail.
Tell me if something is wrong or left out.

Add target to button of collectionview cell inside tableview cell

I have a tableview cell inside which i have added collectionview cell ( for horizontal scrolling).
Now i want to push to other navigation controller on button of any cell of horizontal collectionview. How to do it ? O
Code :
ViewController.swift :
class ViewController: UIViewController {
var categories = ["Action", "Drama", "Science Fiction", "Kids", "Horror"]
}
extension ViewController : UITableViewDelegate { }
extension ViewController : UITableViewDataSource {
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return categories[section]
}
func numberOfSections(in tableView: UITableView) -> Int {
return categories.count
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell") as! CategoryRow
return cell
}
}
CategoryRow.swift
class CategoryRow : UITableViewCell {
#IBOutlet weak var collectionView: UICollectionView!
}
extension CategoryRow : UICollectionViewDataSource {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 12
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "videoCell", for: indexPath) as! VideoCell
cell.button.addTarget(self, action:#selector(ViewController.goToLookAtPage(_:)), for: .touchUpInside)
return cell
}
}
extension CategoryRow : UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let itemsPerRow:CGFloat = 4
let hardCodedPadding:CGFloat = 5
let itemWidth = (collectionView.bounds.width / itemsPerRow) - hardCodedPadding
let itemHeight = collectionView.bounds.height - (2 * hardCodedPadding)
return CGSize(width: itemWidth, height: itemHeight)
}
}
where do i declare goToLookAtPage function ?
VideoCell.swift
class VideoCell : UICollectionViewCell {
#IBOutlet weak var button: UIButton!
}
You need to delclare it
on CategoryRow Class also declare global closure
like
var buttonTapped:((CategoryRow?) -> Void)? = nil
Now we have closure to call
Implement goToLookAtPage as below
func goToLookAtPage(_ sender:UIButton) {
if let btnAction = self.buttonTapped {
btnAction(self)
}
}
Now in your ViewController add following in cellForRowAtIndexPath
cell.buttonTapped = {(cell) -> Void in
//You Got your response , do push in main Thread
}
Hope it helps to you
In your button handler function get the button's position where sender is your button.
let position = sender.convert(CGPoint.zero, to: self.collectionView)
Get the index path for the given position.
let indexPath = self.collectionView?.indexPathForItem(at: position)
Get the model from your data source with the index path.
let model = self.data[indexPath.row]
Now that you have your data model, pass it to your destination and push your view controller or whatever.

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