SubViews是否在collectionView单元格中重复?

时间:2018-06-18 22:59:12

标签: ios swift uicollectionview uistackview

我有一个代表一段时间的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
        }
    }
}

我相信这应该给我带来理想的效果。例如,如果2年内生成3个日期,则会在2年的单元格中创建3个条带。但是,我发现渲染了超过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 个答案:

答案 0 :(得分:1)

看起来您实际上并未重置dequeueReusableCell返回给您的单元格的内容。

dequeueReusableCell为您提供了一个可能已用于优化性能的单元格。该方法的文档说明:

  

如果现有单元格可供重用,则此方法会调用单元格的prepareForReuse()方法。

如果您查看prepareForReuse()的{​​{3}},您会发现您有机会重置单元格的属性,以便您可以重复使用单元格。

如果重置单元格,您可能会发现它开始按照您期望的方式运行。