Bright
Bright

Reputation: 5741

Collection view cellForItemAt indexPath not getting called (Swift)

I created a collection view controller from story board, and set its custom class to ItemCollectionVC, the custom class of its cell to ItemCell, and set its reuse identifier to Cell

Here's my ItemCollectionVC class:

import UIKit

private let reuseIdentifier = "Cell"

class ItemCollectionVC: UICollectionViewController {

var dataSourceItems: [Items] = []
var counterBuildItems: [Items] {
    let weaponItemArray = WeaponItems.weaponItems as [Items]
    let defenseItemArray = DefenseItems.defenseItems as [Items]
    return weaponItemArray + defenseItemArray
}
var freeBuildItems = WeaponItems.weaponItems as [Items]
var captureKrakenItems: [Items] {
    let weaponItemArray = WeaponItems.weaponItems as [Items]
    let abilityItemArray = AbilityItems.abilityItems as [Items]
    return weaponItemArray + abilityItemArray
}

override func viewDidAppear(_ animated: Bool) {

    switch self.presentingViewController!.title! {
    case "CounterBuildVC":
        dataSourceItems = counterBuildItems
    case "FreeBuildVC":
        dataSourceItems = freeBuildItems
    case "CaptureKrakenVC":
        dataSourceItems = captureKrakenItems
    default:
        break
    }
}

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

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

override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier, for: indexPath) as! ItemCell
    cell.cellImage.image = dataSourceItems[indexPath.row].image
    print(dataSourceItems.count)

    return cell
}
}

When the collection view controller is presented, it's empty, what could cause the problem?

Upvotes: 8

Views: 29076

Answers (7)

Mandeep Singh
Mandeep Singh

Reputation: 2855

You have to add your code in viewWillAppear, then it will work properly. /*

override func viewDidAppear(_ animated: Bool) {

switch self.presentingViewController!.title! {
case "CounterBuildVC":
    dataSourceItems = counterBuildItems
case "FreeBuildVC":
    dataSourceItems = freeBuildItems
case "CaptureKrakenVC":
    dataSourceItems = captureKrakenItems
default:
    break
}
}

Like this :-

override func viewWillAppear(_ animated: Bool) {
    
     switch self.presentingViewController!.title! {
case "CounterBuildVC":
    dataSourceItems = counterBuildItems
case "FreeBuildVC":
    dataSourceItems = freeBuildItems
case "CaptureKrakenVC":
    dataSourceItems = captureKrakenItems
default:
    break
}
}
 

*/

Upvotes: 0

Ishaan Gupta
Ishaan Gupta

Reputation: 161

I fixed my problem by initializing UICollectionView properly like the following:

fileprivate let collectionView = UICollectionView(frame: CGRect.zero, collectionViewLayout: UICollectionViewFlowLayout.init()) 

Upvotes: 2

babatunde adewole
babatunde adewole

Reputation: 493

Check if you get the right number of sections in the numberOfItemsInSection method for the collection view.

If you are adding a flow layout to the collection view, remove the flow layout, and check if the collection view cells show now.

If they do, just adjust your collection view flow layout code it should look like this

let _flowLayout = UICollectionViewFlowLayout()
_flowLayout.sectionInset = UIEdgeInsets(top:0, left: 0, bottom: 0, right: 0)
_flowLayout.scrollDirection = .vertical
yourCollectionView.collectionViewLayout = _flowLayout

you can set the inset to fit your use.

Upvotes: 3

Dhaval H. Nena
Dhaval H. Nena

Reputation: 4130

In my case there was a problem with the collection view contentInset, try adding below code in your collection view sub class.


override func layoutSubviews() {
    super.layoutSubviews()
    self.contentInset = UIEdgeInsetsMake(0, 0, 0, 0)
}

override func reloadData() {
    DispatchQueue.main.async {
        super.reloadData()
    }
}

Upvotes: 1

Egzon P.
Egzon P.

Reputation: 4778

Some things that you could easily miss if you use storyboard

1) Don't forget that content in cell must have connected Top, Bottom constraint and content view must have height, by this cell will know to set height for cell. If you don't have these, cell height will be 0, and function cellForItemAt will never get called.

2) You can use cell layout to set dynamic cell and height for cell if you use this function:

    func collectionView(_ collectionView: UICollectionView,layout collectionViewLayout: 
    UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) ->
    CGSize {return CGSize(width: 20.00, height: 20.00)}

Upvotes: 2

dylanthelion
dylanthelion

Reputation: 1770

One of three things caused this problem, pretty much every time I have encountered it, in a TableView or CollectionView:

1) Your ViewController is not the dataSource of your UICollectionView

2) numberOfRows or numberOfSections method returns 0

3) The height of your cell is 0, either due to constraint problems, or a heightForCell method being not/improperly implemented.

It's impossible to say which of these is your problem, and it's always possible that you've encountered something strange. Make certain that none of these is your problems, before exploring less likely options.

Upvotes: 15

Ahmad F
Ahmad F

Reputation: 31645

If you are pretty sure that the dataSource of the collectionView is connected to the viewController (it should be by default), then you should reloadData() because the collectionView reading from dataSourceItems. To understand the case, add a break point in cellForItemAt and add another one in viewDidAppear and check which one is called first?

override func viewDidAppear(_ animated: Bool) {

    switch self.presentingViewController!.title! {
    case "CounterBuildVC":
        dataSourceItems = counterBuildItems
    case "FreeBuildVC":
        dataSourceItems = freeBuildItems
    case "CaptureKrakenVC":
        dataSourceItems = captureKrakenItems
    default:
        break
    }

    collectionView.reloadData()
}

Hope that helped.

Upvotes: 4

Related Questions