CollectionView cellForItemAt never runs

Hi I have been searching for this a lot and couldn't get an appropriet answer.

I am trying to populate a collectionView with data received online using an API.

Data is returned but the collectionView cellForItemaAt never runs because when I use print statements nothing gets displayed.



I can't figure out what the problem is , I looked at these tow links but they werent't helpful :



https://stackoverflow.com/questions/51298015/collectionview-cellforitemat-not-being-called



https://stackoverflow.com/questions/46853189/cellforitemat-is-not-calling-in-collectionview



https://stackoverflow.com/questions/40372326/cellforitemat-never-called-in-a-class-extends-uicollectionviewcontroller



here is the cellForItemAt method :





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

{

collectionView.dequeueReusableCell(withReuseIdentifier: "ItemCollectionViewCell", for: indexPath) as! ItemCollectionViewCell

cell.ItemNameLabel.text = itemArray[indexPath.row].name

print(itemArray[indexPath.row].name)

cell.priceLable.text = itemArray[indexPath.row].price + " " + itemArray[indexPath.row].currency

guard let url : URL = URL(string: itemArray[indexPath.row].image) else {return cell}

cell.imageView.sd_setShowActivityIndicatorView(true)

cell.imageView.sd_setIndicatorStyle(.gray)

cell.imageView.sd_setImage(with: url, placeholderImage: UIImage(named:"placeholderImage"), options: .refreshCached, completed: nil)

return cell

}



here is the method I use to retrieve the data :







func getAllItemsApiMethod()

{

itemArray.removeAll()

if Reachability.sharedInstance.connectedToNetwork()

{

if searchShops == true {

PostDict = ["page" : pageNumber ,"text" : searchKeyword,"searchShop" : "1"]

}else{

PostDict = ["page":"1","text":searchKeyword]

}

print(PostDict)

StartIndicator()

WebServices.getItemsMethod(url: itemsUrl, parameters: PostDict) { (JsonResponse) in

print(JsonResponse)

StopIndicator()

let json : JSON = JSON(JsonResponse)

self.updateItemData(json: json)

print(json)

}

}

else

{

FTIndicator.showToastMessage(Constant.NoInternet)

}

}

func updateItemData (json : JSON) {

let item = Item()

for i in 0...json["data"].count - 1{

item.name = json["data"][i]["title_ku"].stringValue

item.price = json["data"][i]["price"].stringValue

item.image = json["data"][i]["image"].stringValue

item.currency = json["data"][i]["currency"].stringValue

}

// useItemsCell = true

self.collectionViewHome.reloadData()

}







and here is the method i use to call the getAllItemsAPI :






func textFieldShouldReturn(_ textField: UITextField) -> Bool {

guard let searchKeyword = txtFldSearch.text else {return false}

getAllItemsApiMethod()

collectionViewHome.reloadData()

self.view.endEditing(true)

txtFldSearch.text = ""

return true

}



here is the numberOfItems method :



func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int

{

return itemArray.count

}



I have been searching for quite sometime to find an answer. Any help is really appreciated

Is the collection view’s dataSource property set to your view controller? It’s possible there’s something strange going on with the way you are instantiating the collection view or setting up outlets. Perhaps you could show any code related to that.

When you post code, please format it with <> tool. And avoid adding lots of blank lines, that makes reading more difficult.

Note: Swift 5 not here yet, so I suppose you use Swift 4.


In getAllItemsApiMethod, you clear itemArray (itemArray.removeAll()). Where do you populate it ?


     func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell        {
         
            collectionView.dequeueReusableCell(withReuseIdentifier: "ItemCollectionViewCell", for: indexPath) as! ItemCollectionViewCell
                cell.ItemNameLabel.text = itemArray[indexPath.row].name
  
                print(itemArray[indexPath.row].name)
  
                cell.priceLable.text = itemArray[indexPath.row].price + " " + itemArray[indexPath.row].currency
  
                guard let url : URL = URL(string:  itemArray[indexPath.row].image) else {return cell}
  
                cell.imageView.sd_setShowActivityIndicatorView(true)
                cell.imageView.sd_setIndicatorStyle(.gray)
                cell.imageView.sd_setImage(with: url, placeholderImage: UIImage(named:"placeholderImage"), options: .refreshCached, completed: nil)
                
                return cell
          
            }
     func getAllItemsApiMethod()
        {
            itemArray.removeAll()
            if Reachability.sharedInstance.connectedToNetwork()
            {
                if searchShops == true {
                    PostDict = ["page" : pageNumber ,"text" : searchKeyword,"searchShop" : "1"]
                }else{
                       PostDict = ["page":"1","text":searchKeyword]
                }
             
                print(PostDict)
             
                StartIndicator()
                WebServices.getItemsMethod(url: itemsUrl, parameters: PostDict) { (JsonResponse) in
                    print(JsonResponse)
                    StopIndicator()
                    let json : JSON = JSON(JsonResponse)
                
                   self.updateItemData(json: json)
                    print(json)
                }
            }
            else
            {
                FTIndicator.showToastMessage(Constant.NoInternet)
            }
          
        }
      
        func updateItemData (json : JSON) {
            let item = Item()
         
            for i in 0...json["data"].count - 1{
                item.name = json["data"][i]["title_ku"].stringValue
                item.price = json["data"][i]["price"].stringValue
                item.image = json["data"][i]["image"].stringValue
                item.currency = json["data"][i]["currency"].stringValue
              
            }
          
          //  useItemsCell = true
             self.collectionViewHome.reloadData()
        }



    func textFieldShouldReturn(_ textField: UITextField) -> Bool {
          
            guard let searchKeyword = txtFldSearch.text else {return false}         
            getAllItemsApiMethod()
            
            collectionViewHome.reloadData()
         
            self.view.endEditing(true)
            txtFldSearch.text = ""
          
            return true
          
        }


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

I am getting similar issue. numberOfItemsInSection is being called and is returning 2, in my case. but cellForItemAt is not being called.

I'm having the same problem as @lozzoc, my view controller is a standard UIViewController, there is a UICollectView on the page along with other UI elements.

I have added an extension for my view controller that implements UICollectionViewDataSource

    // MARK: - UICollectionViewDataSource
    func numberOfSections(in collectionView: UICollectionView) -> Int {
        if #available(iOS 14.0, *) {
            os_log(.debug, "UICollectionViewDataSource: numberOfSections: 1")
        }
        return 1
    }

    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        if #available(iOS 14.0, *) {
            os_log(.debug, "UICollectionViewDataSource: numberOfItemsInSection: \(self.searchTerms.count)")
        }
        return searchTerms.count
    }

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        if #available(iOS 14.0, *) {
            os_log(.debug, "UICollectionViewDataSource: cellForItemAt: \(indexPath)")
        }
        return cell(from: collectionView, for: indexPath)
    }

    func cell(from collectionView: UICollectionView, for indexPath: IndexPath) -> SearchTermCell {
        if #available(iOS 14.0, *) {
            os_log(.debug, "RecomendedPageContentViewController: for \(indexPath)")
        }

        func extractViewModel(at indexPath: IndexPath) -> SearchTermCell.ViewModel {
            if #available(iOS 14.0, *) {
                os_log(.debug, "extractViewModel: at \(indexPath)")
            }
            let viewModel: SearchTermCell.ViewModel
            let value = getData(for: indexPath)
            viewModel = self.viewModel(for: value)
            return viewModel
        }

        let cell: SearchTermCell = collectionView.dequeueReusableCell(withReuseIdentifier: "SearchTermCell", for: indexPath) as! SearchTermCell
        configure(cell: cell, with: extractViewModel(at: indexPath))
        cell.setNeedsLayout()
        cell.sizeToFit()
        return cell
    }

I included cell(from collectionView: UICollectionView, for indexPath: IndexPath), but cellForItemAt is never called.

The collection view is connected to the view controller (via a Storyboard)

    @IBOutlet weak var collectionView: UICollectionView!

in viewDidLoad the view controller is assigned as the datasource

self.collectionView.dataSource = self

In the storyboard the UICollectViewCell has its class set to my custom UICollectionViewCell

class SearchTermCell: UICollectionViewCell {
    @IBOutlet private weak var searchLabel: UILabel!


    var viewModel = ViewModel() {
        didSet {
            backgroundColor = UIColor.appColor(.title)
            searchLabel.text = viewModel.title
            searchLabel.font = .titleFont
            searchLabel.textColor = UIColor.appColor(.cellBackColour)

            if #available(iOS 14.0, *) {
                os_log(.debug, """

                       -----------------------------
                       searchLabel.text: \(self.viewModel.title)
                       -----------------------------
                       """)
            }
        }
    }
}

Any ideas would be appreciated.

CollectionView cellForItemAt never runs
 
 
Q