0

I'm trying to use the current CollectionViewcell's IndexPath to access data from a dictionary. The dictionary's keys are of type Int. This CollectionView has "full page" cells, meaning that each cell takes up the full view area where I am using horizontal scrolling (paging enabled) to navigate between cells.

The dictionary is :

var dataFromServer: [Int: [VillageFestival]]?

Each CollectionViewCell has a TableView inside it, where I plan to have a variable number of rows, depending on how many items there are in [VillageFestival]

However, in CollectionView cellForItemAt indexPath the behaviour of the method is causing some trouble, as printing indexPath.item or setting it as my navigationController's title, returns odd but "understandable" results given how I think dequeueReusableCell works?...

Example: the current index is 0. When I scroll to the right, the current index is now 2. If I navigate to page 6 and then one page back, the current index indicates 3.

I have changed my dictionary keys from Date to String and now to Int, in an attempt to simplify logic.. But the problem persists. I am using a global pageIndex: Int that is being updated inside CollectionView cellForItemAt

override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {

    pageIndex = indexPath.item

    self.navigationController?.navigationBar.topItem?.title = String(pageIndex)

    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "collectionViewCell", for: indexPath) as! CollectionViewCell

    // CollectionViewCell resize to CollectionView Bounds
    cell.tableViewCellOffsets = (UIApplication.shared.statusBarFrame.size.height + (self.navigationController?.navigationBar.frame.height ?? 0.0) , self.tabBarController?.tabBar.frame.height ?? 0)
    return cell

}

In Tableview numberOfRowsInSection, I'm using pageIndex to access the dictionary values.

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

    guard let festivals = dataFromServer?[pageIndex]  else {return 0}

    return festivals.count

}

With my current code, the app displays 0 rows for some pages and 1 row for others. My guess is that the collectionView's cellForItemAt is called before (also possibly after?) the tableView's methods and this makes using a global pageIndex unreliable...

Thanks!

Renato Silva
  • 51
  • 10
  • `cellForItemAt` is also called for cells that are yet not on screen so that's why your `pageIndex` is not reflecting exactly what you see. I don't know how you are handling the nested tableView here, but one approach could be to pass the `festivals` array each time you dequeue the collectionViewCell and call `reloadData`. – Fabio Felici Jan 07 '19 at 18:17
  • I think you are on the right track of the dequeable cells affecting the index path. I think you should increment the pageIndex based on gesture recognizer or pressing the specific page. (so if swipe right, += 1. Press on page 6, pageIndex = 5, etc..) – Mocha Jan 07 '19 at 18:25
  • How do you set navigationController's title ? You should use cellForItem(at: indexPath) to get the content of the cell. – claude31 Jan 07 '19 at 18:43

1 Answers1

0

Try this playground, it might help you:

import UIKit
import PlaygroundSupport

class Cell: UICollectionViewCell, UITableViewDataSource {

    var data: [Int]! = [] {
        didSet {
            tableView.reloadData()
        }
    }
    private let tableView: UITableView

    override init(frame: CGRect) {
        tableView = UITableView(frame: .zero, style: .plain)
        super.init(frame: frame)
        tableView.register(UITableViewCell.self, forCellReuseIdentifier: "Cell")
        tableView.dataSource = self
        tableView.translatesAutoresizingMaskIntoConstraints = false
        contentView.addSubview(tableView)
        NSLayoutConstraint.activate([
            tableView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor),
            tableView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor),
            tableView.topAnchor.constraint(equalTo: contentView.topAnchor),
            tableView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor)
        ])
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError()
    }

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

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

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
        cell.textLabel?.text = String(data[indexPath.item])
        return cell
    }
}

class VC: UICollectionViewController {

    let data = [
        0: [1, 2, 3, 4, 5],
        1: [6, 4],
        2: [5, 5, 5, 5, 6],
        3: [9, 9, 8, 4, 5, 5, 5]
    ]

    override init(collectionViewLayout layout: UICollectionViewLayout) {
        super.init(collectionViewLayout: layout)
        collectionView.isPagingEnabled = true
        collectionView.register(Cell.self, forCellWithReuseIdentifier: "Cell")
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError()
    }

    override func numberOfSections(in collectionView: UICollectionView) -> Int {
        return 1
    }

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

    override func viewDidLayoutSubviews() {
        (collectionViewLayout as? UICollectionViewFlowLayout)?.itemSize = collectionView.bounds.size
    }

    override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) as! Cell
        cell.data = data[indexPath.item]
        return cell
    }

}

let layout = UICollectionViewFlowLayout()
layout.scrollDirection = .horizontal
PlaygroundPage.current.liveView = VC(collectionViewLayout: layout)
Fabio Felici
  • 2,841
  • 15
  • 21