Search code examples
swiftuicollectionviewcell

cellForItemAt function not being called


The function isn't being called and displaying no data. My code is below and I'm not getting any errors printed in the console. I set a break point on the function and it does not catch.

I was previously getting an index out of bounds crash but changed some code and now the collection view does not populate.

import UIKit
import CoreLocation

class ForecastController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {

    @IBOutlet weak var collectionView: UICollectionView!

    let rainArray : [Int] = [1,2,3,4,5,6,7,8,9,10]
    let cloudyArray : [Int] = [26,27,28,29,30]
    let snowArray : [Int] = [13,14,15,16]
    let sunnyArray : [Int] = [31,32,33,34]
    let stormArray : [Int] = [41,42,43,44,45,46,47]

    var Forecast : [Forecast] = []

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

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

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: ForecastCell.reuseId, for: indexPath) as? ForecastCell else {
                return collectionView.dequeueReusableCell(withReuseIdentifier: "blank", for: indexPath)
        }
        let data = Forecast[indexPath.item]
        cell.summary.text = data.text
        cell.highLow.text = "\(data.high) | \(data.low)"
        cell.dayLabel.text = data.day

        if self.rainArray.contains(data.code) == true {
            cell.weatherIcon.image = UIImage(named: "Rain.png")
        } else if self.snowArray.contains(data.code) == true {
            cell.weatherIcon.image = UIImage(named: "snow.png")
        } else if self.cloudyArray.contains(data.code) == true {
            cell.weatherIcon.image = UIImage(named: "cloudy.png")
        } else if self.sunnyArray.contains(data.code) == true {
            cell.weatherIcon.image = UIImage(named: "sunny.png")
        } else if self.stormArray.contains(data.code) == true {
            cell.weatherIcon.image = UIImage(named: "storm.png")
        } else {
            cell.weatherIcon.image = UIImage(named: "cloudy.png")
        }
        return cell
    }

    func getWeather() {
        YahooWeatherAPI.shared.weather(lat: "\(currentLat!)", lon: "\(currentLong!)", failure: { (error) in
            print(error.localizedDescription)
            print("Error pulling weather data")
        }, success: { (response) in
            let data = response.data
            do {
                let weather = try JSONDecoder().decode(Weather.self, from: data)
                for x in weather.forecasts {
                    // populate collection view
                    self.Forecast = [x]
                }
            } catch {
                print(error)
            }
        }, responseFormat: .json, unit: .imperial)
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        collectionView.dataSource = self
        collectionView.delegate = self

        getWeather()
        // Do any additional setup after loading the view.
    }
}
class ForecastCell: UICollectionViewCell {

    @IBOutlet weak var weatherIcon: UIImageView!
    @IBOutlet weak var dayLabel: UILabel!
    @IBOutlet weak var summary: UILabel!
    @IBOutlet weak var highLow: UILabel!
    public static var reuseId : String = "forecastCell"

}

Solution

  • You should call reloadData() after you got data from Yahoo:

    do {
        let weather = try JSONDecoder().decode(Weather.self, from: data)
        for x in weather.forecasts {
            // populate collection view
            self.Forecast = [x]
        }
        collectionView.reloadData()
    } catch {
        print(error)
    }
    

    Your delegate doesn't know that data has changed so cellForItemAt isn't called.