0

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 I get the below (see picture) (and obviously index out of range):

Print(array[indexPath.row].details.values)

So using the example from the photo, how can I get the following:

  • Outer tableViewCell (1)
    • CollectionViewCell (1)
      • label - "1"
    • CollectionViewCell (2)
      • label - "3"
    • CollectionViewCell (3)
      • label - "5"
  • Outer tableViewCell (2)
    • CollectionViewCell (1)
      • label - "7"

Also as you may of noticed its the array is not in order, is it possible to reorder so its:

["1": 1, "2": 3, "3": 5]

Any help is greatly appreciated, many thanks!!

My Array:

Data to display in label

Kuldeep
  • 4,466
  • 8
  • 32
  • 59
WH48
  • 737
  • 1
  • 7
  • 24
  • You mean the array is an Array of Dictionary like let array = [["2":3,"1": 1,"3":5,"1":7]]. ? – Rizwan Mehboob Jun 25 '18 at 12:58
  • The array is [["2": 3, "1": 1, "3": 5]], [["1":7]], therefore the first tableViewCell should have 3 collectionViewCells with their respective labels text as 1, 3, 5 (note I would like them to be reordered). And the second tableViewCell should have 1 collectionViewCell with its label being 7. Many thanks! – WH48 Jun 25 '18 at 13:04

3 Answers3

2

Based on your requirements here is the code

import UIKit

class ViewController: UIViewController,UITableViewDelegate,UITableViewDataSource {

    // Global Variable
    var tableView: UITableView!
    var dataArray = [["2": 3, "1": 1, "3": 5], ["1":7]]

    override func viewDidLoad() {
        super.viewDidLoad()

        tableView = UITableView(frame: self.view.bounds)
        tableView.delegate = self
        tableView.dataSource = self
        self.view.addSubview(tableView)

        tableView.register(TableViewCell.self, forCellReuseIdentifier: "TableViewCell")
    }

    func numberOfSectionsInTableView(tableView: UITableView) -> Int {
        return 1
    }

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return dataArray.count
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
            let cell: TableViewCell = tableView.dequeueReusableCell(withIdentifier: "TableViewCell", for: indexPath as IndexPath) as! TableViewCell
     //   Passing data to cellection cell
            cell.cellData = dataArray[indexPath.row]
            cell.backgroundColor = UIColor.groupTableViewBackground
            return cell


    }

}

class TableViewCell: UITableViewCell, UICollectionViewDataSource, UICollectionViewDelegate {

    var collectionView: UICollectionView!
    var cellData = [String: Int]()

    override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)

        let layout = UICollectionViewFlowLayout()
        layout.scrollDirection = UICollectionViewScrollDirection.horizontal

        collectionView = UICollectionView(frame: self.bounds, collectionViewLayout: layout)
        collectionView.delegate = self
        collectionView.dataSource = self
        collectionView.register(CollectionCell.self, forCellWithReuseIdentifier: "CollectionViewCell")
        collectionView.backgroundColor = UIColor.clear

        self.addSubview(collectionView)
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }

    // MARK: UICollectionViewDataSource
    func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int {
        return 1
    }


    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return cellData.count
    }

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell: CollectionCell = collectionView.dequeueReusableCell(withReuseIdentifier: "CollectionViewCell", for: indexPath as IndexPath) as! CollectionCell
        cell.textLable.text = String(Array(cellData)[indexPath.row].value) // Please check here is some casting 
        cell.backgroundColor = .black
        return cell
    }
}

class CollectionCell: UICollectionViewCell {

    let textLable: UILabel = {
        let label = UILabel(frame: CGRect(x: 0, y: 0, width: 20, height: 20))
        label.textColor = .white
        label.translatesAutoresizingMaskIntoConstraints = true
        label.textAlignment = .center
        return label
    }()

    override init(frame: CGRect) {
        super.init(frame: frame)
        setupLayout()
    }

    private func setupLayout() {
        addSubview(textLable)
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

I hope it solves your issue.

Result

enter image description here

Rizwan Mehboob
  • 1,333
  • 17
  • 19
  • Hi rizwan, thank you so much!!! I’m not currently near my computer but it looks perfect! I’ll upvote you once I’ve tested it out! One last thing, is it possible to reorder the array so the first tableViewCell is 1, 3, 5 instead of 3, 1, 5? Thank you so much once again – WH48 Jun 25 '18 at 13:48
  • I am glad it helped you , for reorder just change the data array way you want like [["1":7],["2": 3, "1": 1, "3": 5]]. – Rizwan Mehboob Jun 25 '18 at 14:14
  • Sorry no I meant so that I can re order the arrays values so it’s [[“1”: 1, “2”: 3, “3”: 5]]. Basically so that the first value of each dictionary is 1, 2, 3? Without doing it manually, is there a bit or code that makes this possible? Please note that these values don’t need to be strings, I can cast them to an Int value when I retrieve them from the server. Thanks! – WH48 Jun 25 '18 at 14:26
  • 1
    For changing order you have to use to sort your data based on you need, you can sort array based on values and sorting rule and you can also sort dictionary based on keys or values https://stackoverflow.com/questions/24090016/sort-dictionary-by-values-in-swift and second like is https://stackoverflow.com/questions/31088974/use-sort-for-multidimensional-array-array-in-array-in-swift – Rizwan Mehboob Jun 25 '18 at 16:03
  • Hi rizwan, it works perfectly, thank you so much again! You've been a huge help! – WH48 Jun 25 '18 at 20:05
0

If I understood it correctly you have an array with this, slightly odd, format

array = [[["2": 3, "1": 1, "3": 5]], [["1":7]]]

Since the collection view is inside a table view I assume you have implemented the NSTableViewDataSource and then you can save the current row for the table view as a property in tableView: viewFor: and thus get the array to use with that property. Since you have an array within an array we need to get the first item in that array and then filter that item (a dictionary) where the key matches the current indexPath.row

let row = String(indexPath.row + 1)
let item = array[currentTableViewRow][0].filter {$0.key = row}
if !item.isEmpty {
     label.text = item.value
}
Joakim Danielson
  • 43,251
  • 5
  • 22
  • 52
  • Hi Joakim, thanks so much for the reply! I’ll test it out later when I’m near my computer and give you an upvote if it works! Thank so much once again – WH48 Jun 25 '18 at 13:51
  • Hi Joakim, really sorry but please may you explain where "currentTableViewRow" came from? Thank you! – WH48 Jun 25 '18 at 20:07
  • It’s a property you set in your table view data source method I mentioned in the text. – Joakim Danielson Jun 26 '18 at 04:52
-1

Conver it to Array With this :

Array(array[indexPath.row].details.values)

And print this value You get proper array in proper order.

I hope it will help you,

Thank you.

Vishal Patel
  • 717
  • 6
  • 11