代码之家  ›  专栏  ›  技术社区  ›  BigBoy1337

在集合视图单元格中复制子视图?

  •  1
  • BigBoy1337  · 技术社区  · 7 年前

    我有一个代表一段时间的集合视图。每个单元格是一个月。在每个单元格中都有一个水平堆栈视图,其中每个视图代表一天。

    如果你想尝试一下,整个项目就在这里: https://github.com/AlexMarshall12/iOS-timeline

    在我的视图控制器中,我生成一个随机的日期数组。每次在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 回复  |  直到 7 年前
        1
  •  1
  •   MultiColourPixel    7 年前

    看起来你并不是在重置由返回给你的单元格的内容 dequeueReusableCell

    为您提供一个可能已经用于优化性能的单元。方法说明文件:

    prepareForReuse()

    如果您查看 documentation 准备重新使用()

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