BigBoy1337
BigBoy1337

Reputation: 5003

How to color SubViews in a collectionView Cell's cellForItemAt?

I am trying to build a timeline of sorts. I have a view controller which contains a collectionView. Each collectionView cell represents a month's worth of data. In each cell I have a stackView. This stackView contains 30 subviews which each represent a day of data.

The full project is here if you wanna try it out: https://github.com/AlexMarshall12/iOS-timeline

My current approach for coloring each dayCell subview is to create all the subviews in the cell initially in the awakeFromNib of the custom cell.

class MonthCollectionViewCell: UICollectionViewCell {

    @IBOutlet weak var stackView: UIStackView!
    var dayViews: [Int:UIView] = [:]

    override func awakeFromNib() {
        super.awakeFromNib()
        for i in 1...30 {
            let tick = UIView()
            dayViews[i] = tick
            self.stackView?.addArrangedSubview(tick)
        }
    }

}

Note that I also build a dictionary that indexes each subview in the cell from 1-30.

Then in my viewController, in my cellForItemAt method for my collectionView, I look to see for that month which days are in the data using my "dates" function. I then lookup this view with the dictionary I build earlier and color it red.

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "MonthCollectionViewCell", for: indexPath) as! MonthCollectionViewCell
    cell.backgroundColor = UIColor.gray
    let dayViews = cell.dayViews
    let firstDate = dates.first
    let index = indexPath.item
    let monthDate = Calendar.current.date(byAdding: .month, value: index, to: firstDate as! Date)
    let monthInt = Calendar.current.component(.month, from: monthDate!)
    let yearInt = Calendar.current.component(.year, from: monthDate!)
    let monthDates = dates(self.dates as! [Date], withinMonth: monthInt, withinYear: yearInt)
    for date in monthDates {
        let dayInt = date.interval(ofComponent: .day, fromDate: (monthDate?.startOfMonth())!)
        let tick = dayViews[dayInt]
        print(tick,"tick")
        tick?.backgroundColor = UIColor.red
        }
    return cell
}

func dates(_ dates: [Date], withinMonth month: Int, withinYear year: Int) -> [Date] {
    let calendar = Calendar.current
    let components: Set<Calendar.Component> = [.month,.year]
    print(components,"components")
    let filtered = dates.filter { (date) -> Bool in
        let monthAndYear = calendar.dateComponents(components, from: date)
        return (monthAndYear.month == month && monthAndYear.year == year)
    }
    return filtered
}

Currently, everything shows up just as grey month cells that can be scrolled right to left. Even though my console tells me its finding matches to color, it doesn't appear to be coloring them. What am I doing wrong in this approach/implementation?

Upvotes: 0

Views: 110

Answers (1)

matt
matt

Reputation: 535850

When you have a case of "I don't see the view I expect to see", run your app in the simulator and, back in Xcode, fire up the View Debugger.

In this case, when you do that, you'll see your error immediately: all your "ticks" are invisible because you are sending zero-size plain vanilla UIViews to your "Fill distribution" stack view as arranged subviews. The stack view has no idea what do with these. So they end up with no size, which makes them invisible.

Change the "Fill distribution" to "Fill Equally distribution" in the xib editor, run the app again, and presto, you'll start to see some ticks!

Upvotes: 2

Related Questions