SubViews дублируются в ячейках collectionView?

У меня есть collectionView, который представляет промежуток времени. Каждая клетка - это месяц. В каждой ячейке есть горизонтальное представление стека, где каждое представление представляет день.

Полный проект находится здесь, если вы хотите попробовать его: https://github.com/AlexMarshall12/iOS-timeline

В моем ViewController я генерирую случайный массив дат. Каждый раз, когда ячейка вызывается в cellForItemAt, пользовательская функция находит даты в массиве, которые находятся в месяце ячейки.

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "MonthCollectionViewCell", for: indexPath) as! MonthCollectionViewCell
    cell.backgroundColor = UIColor.gray
    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!)
    cell.monthLabel.text = String(monthInt)+" "+String(yearInt)
    cell.year = yearInt
    cell.month = monthInt
    let monthDates = dates(self.dates as! [Date], withinMonth: monthInt, withinYear: yearInt)
    cell.colorViews(monthDates:monthDates)
    return cell
}
    func dates(_ dates: [Date], withinMonth month: Int, withinYear year: Int) -> [Date] {
    let calendar = Calendar.current
    let components: Set<Calendar.Component> = [.month,.year]
    let filtered = dates.filter { (date) -> Bool in
        let monthAndYear = calendar.dateComponents(components, from: date)
        return (monthAndYear.month == month && monthAndYear.year == year)
    }
    return filtered
}

Они передаются в пользовательский класс ячеек, и он находит подпредставления, которые представляют эти дни, и окрашивает их так:

class MonthCollectionViewCell: UICollectionViewCell {

    @IBOutlet weak var monthLabel: UILabel!
    @IBOutlet weak var stackView: UIStackView!
    var year: Int?
    var month: Int?

    override func awakeFromNib() {
        super.awakeFromNib()
        for _ in 0...30 {       //for the 31 days in a month...
            let tick = UIView()
            self.stackView?.addArrangedSubview(tick)
        }
    }

    func colorViews(monthDates: [Date]){
        for date in monthDates {
            let dayIndex = Calendar.current.component(.day, from: date)
            let tick = stackView.arrangedSubviews[dayIndex]
            tick.backgroundColor = UIColor.red
        }
    }
}

Я считаю, что это должно дать мне желаемый эффект. Например, если есть 3 даты, сгенерированные за 2 года, это создаст 3 полоски за 2 года ячеек месяца. Тем не менее, я обнаружил, что визуализируется более 3 полос, почти как если бы они дублировали подпредставление во многих ячейках.

Вот как это выглядит сейчас: https://imgur.com/a/ZNSmIS8. Обратите внимание, что это было с 3 датами. 5 полос появляются. Кажется, что прокрутка вперед и назад добавляет полосы, как будто cellForItemAt вызывается не в той ячейке? Я не совсем уверен.

Любые советы о том, что я делаю неправильно в этой реализации, были бы потрясающими.

Изменить: я добавил этот метод в свой пользовательский класс ячейки:

override func prepareForReuse() {
    super.prepareForReuse()
    for each_view in self.subviews {
        print("Cleared!")
        each_view.backgroundColor = UIColor.clear
    }
}

Та же проблема все еще возникает, особенно с очень большим диапазоном времени и / или быстрой прокруткой

1 ответ

Решение

Не похоже, что вы на самом деле сбрасываете содержимое ячеек, которые возвращаются вам dequeueReusableCell,

dequeueReusableCell предоставляет ячейку, которая, возможно, уже использовалась для оптимизации производительности. Документация по методу примечания:

Если существующая ячейка была доступна для повторного использования, этот метод вызывает ячейку prepareForReuse() метод вместо.

Если вы посмотрите документацию для prepareForReuse(), вы обнаружите, что у вас есть шанс сбросить свойства ячейки, чтобы вы могли использовать ячейку повторно.

Если вы сбросите ячейку, вы, вероятно, обнаружите, что она начинает вести себя так, как вы ожидаете.

Другие вопросы по тегам