子视图在 collectionView 单元格中被复制?
SubViews being duplicated across collectionView cells?
我有一个表示时间跨度的 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,它找到代表那些日子的子视图并像这样给它们着色:
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 一样?我不太确定。
任何关于我在这个实现中做错了什么的建议都会很棒。
编辑:我已将此方法添加到我的自定义单元格中 class:
override func prepareForReuse() {
super.prepareForReuse()
for each_view in self.subviews {
print("Cleared!")
each_view.backgroundColor = UIColor.clear
}
}
同样的问题仍然存在,尤其是在很长的时间范围内and/or快速滚动
您似乎并没有真正重置 dequeueReusableCell
返回给您的单元格的内容。
dequeueReusableCell
为您提供了一个单元格,该单元格可能已被使用以优化性能。方法注释的文档:
If an existing cell was available for reuse, this method calls the cell’s prepareForReuse()
method instead.
如果您查看 prepareForReuse()
的 documentation,您会发现您有机会重置单元格的属性,以便您可以重复使用该单元格。
如果您重置单元格,您可能会发现它开始以您期望的方式运行。
我有一个表示时间跨度的 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,它找到代表那些日子的子视图并像这样给它们着色:
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 一样?我不太确定。
任何关于我在这个实现中做错了什么的建议都会很棒。
编辑:我已将此方法添加到我的自定义单元格中 class:
override func prepareForReuse() {
super.prepareForReuse()
for each_view in self.subviews {
print("Cleared!")
each_view.backgroundColor = UIColor.clear
}
}
同样的问题仍然存在,尤其是在很长的时间范围内and/or快速滚动
您似乎并没有真正重置 dequeueReusableCell
返回给您的单元格的内容。
dequeueReusableCell
为您提供了一个单元格,该单元格可能已被使用以优化性能。方法注释的文档:
If an existing cell was available for reuse, this method calls the cell’s
prepareForReuse()
method instead.
如果您查看 prepareForReuse()
的 documentation,您会发现您有机会重置单元格的属性,以便您可以重复使用该单元格。
如果您重置单元格,您可能会发现它开始以您期望的方式运行。