iosswift3uicollectionviewcell

Why do I get nil in my Collection View Cell?


I am using Alamofire but in that case when I debug the Alamofire code does not execute and now I tried manually creating the url and setting the headers and then calling my API URL.

My collection view class is as follows:

//
//  CategoryViewController.swift
//  iRate
//
//  Created by Ammar Khan on 16/08/2017.
//  Copyright © 2017 theistudio. All rights reserved.
//

import UIKit
import Alamofire
import SwiftyJSON
import SDWebImage

class CategoryViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate
{
    @IBOutlet var myCollectionView: UICollectionView!
    var catArr:[String] = []
    var catImage:[String] = []
   
    let categoriesUrl = "http://127.0.0.1:8000/api/places/categories"

    override func viewDidLoad() {
        super.viewDidLoad()
        
        // Do any additional setup after loading the view.
    }
    
    override func viewDidAppear(_ animated: Bool) {

       loadCatList()
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
    
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return 2
    }
    
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for:indexPath) as! CategoryCell
        print("Reached over here \(self.catArr.count)")
        cell.categoryName.text = self.catArr[indexPath.row]
        return cell
    }
    
    func loadCatList(){
        let networkSession = URLSession.shared
        
        var request = URLRequest(url: URL(string: self.categoriesUrl )!)
        
        request.setValue("application/json", forHTTPHeaderField: "Content-Type")
        
        let dataTask = networkSession.dataTask(with: request) { (data, response, error) in
            print("Data downloaded")
            
            let jsonReadable = NSString(data: data!, encoding: String.Encoding.utf8.rawValue)
            
            print(jsonReadable!)
            do{
                
                let json = JSON(jsonReadable!)
                
                for (_,json):(String, JSON) in json {
                    let catName  = json["category_name"].stringValue
                    let catImage = json["image"].stringValue
                    
                    self.catArr.append(catName)
                    self.catImage.append(catImage)
                }
            }
            catch{
                print("we have a JSON exception")
            }
        }
        //
        dataTask.resume()
        print("Downloading data")
    }
    
    func getCount(){
        print(self.catArr.count)
    }
}

I have tried various methods to add data to my dictionaries but I failed and it is giving me nil. I am not sure what am I doing wrong over here.

PS: This is not what I want to retrieve and is just for testing purpose therefore receiving just two values and adding them to dict.

Final Result:

As the answer suggested below was one of the problems and after that the way I was receiving data and appending them into my arrays was some how wrong so replacing the following code inside my do statement made it work.

let json = JSON(data!)
    
print("The json data is \(json)")

for (_,json):(String, JSON) in json {
   
    let catName = json["category_name"].stringValue
    print("The catImage is \(catName)")
    let catImage = json["image"].stringValue
    self.catArr.append(catName)
    self.catImage.append(catImage)
}

DispatchQueue.main.async {
    self.myCollectionView.reloadData()
}

Solution

  • You are receiving nil because network call is async, so when your table is displayed it is nil at that moment , and when the data comes you do not reload collectionview, so you need to add the following after for-in loop of JSON

    DispatchQueue.main.async {
      self.myCollectionView.reloadData()
    }
    

    Update:

    You should return the number of items as the number of elements in your datasource, which in this case is self.catArr, so modify your code as follows:

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