当 collectionview 刷新时,CollectionView 单元格的计时器会混淆
Posted
技术标签:
【中文标题】当 collectionview 刷新时,CollectionView 单元格的计时器会混淆【英文标题】:CollectionView cell's timers get mixed up when collectionview refreshes 【发布时间】:2019-01-01 22:45:18 【问题描述】:我有一个 collectionView,它在每个单元格中都包含计时器。但是,当应用程序启动时,所有计时器都可以正常工作,但是,当我刷新集合视图时,所有计时器都会混淆并且到处都是。我很确定这与以前的计时器没有关闭有关。
集合视图代码:
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "contestsCell", for: indexPath) as! ContestsCollectionViewCell
cell.nameLabel.text = listingArray[indexPath.row].name
let arr = [listingArray[indexPath.row].expiryDate, cell.expiryDateLabel] as [AnyObject]
timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(updateCounting), userInfo: arr, repeats: true)
return cell
定时器功能代码:
@objc func updateCounting(timer:Timer)
// here we set the current date
var dateArray: [AnyObject] = timer.userInfo as! [AnyObject]
let itemDate = dateArray[0] as! String
var dateList = itemDate.components(separatedBy: "-")
let dateLabel = dateArray[1] as! UILabel
let date = NSDate()
let calendar = Calendar.current
let components = calendar.dateComponents([.hour, .minute, .month, .year, .day, .second], from: date as Date)
let currentDate = calendar.date(from: components)
let userCalendar = Calendar.current
// here we set the due date. When the timer is supposed to finish
let competitionDate = NSDateComponents()
competitionDate.year = Int(dateList[0])!
competitionDate.month = Int(dateList[1])!
competitionDate.day = Int(dateList[2])!
competitionDate.hour = 00
competitionDate.minute = 00
competitionDate.second = 00
let competitionDay = userCalendar.date(from: competitionDate as DateComponents)!
//here we change the seconds to hours,minutes and days
let CompetitionDayDifference = calendar.dateComponents([.day, .hour, .minute, .second], from: currentDate!, to: competitionDay)
//finally, here we set the variable to our remaining time
let daysLeft = CompetitionDayDifference.day
let hoursLeft = CompetitionDayDifference.hour
let minutesLeft = CompetitionDayDifference.minute
let secondsLeft = CompetitionDayDifference.second
if competitionDay > currentDate as! Date
//Set countdown label text
dateLabel.text = "\(daysLeft ?? 0): \(hoursLeft ?? 0): \(minutesLeft ?? 0): \(secondsLeft ?? 0)"
刷新collectionView的代码
@objc func loadData()
retrieveContests()
listingArray.removeAll()
self.refresher.endRefreshing()
【问题讨论】:
【参考方案1】:我认为您的问题与您将单元格出列这一事实有关。因为这背后的原理是 ios 会重用现有的单元格对象,这可能会导致一些问题。
例如在您使用 countdown1 和计时器创建 cell1 的方法中,与 cell2 和 countdown2 (+计时器)相同。一旦你重新加载你的collectionView cell1 和cell2 将被重用,但现在cell1 将有一个不同的索引路径,因此用于countdown2,并且还会创建一个新的计时器。
这可能会导致您的计时器在过程中混淆的问题,据我在您的代码中看到的,您也永远不会停止任何计时器,所以我会说您的假设是正确的。每次重新加载集合视图时,您都会创建更多计时器。
我解决这个问题的建议是:在每个包含用于计算倒计时的日期对象的单元格上创建一个属性。然后只需使用一个计时器来通知所有单元格自行更新其内容。也许您可以为此使用 NotificationCenter。 这种(或类似的方法)应该可以帮助您并避免维护所有这些计时器的整个问题。
【讨论】:
您可以查看my answer 以获得类似的tableview 方法;将其调整为集合视图应该非常简单 @Paulw11 谢谢,我懒得实际创建相同的代码;)这是一种方法。但是对于这种情况,我仍然会寻求一个只有一个计时器的解决方案。我的理由是:因为(据我了解)我们正在处理某些事件(“竞赛”)的倒计时,我认为它们应该以 1 秒的间隔同时更改(多个计时器不能保证)并且不是单独停止/启动。因此,我们不需要为每个单元管理计时器的麻烦 我的代码有一个Timer
;视图控制器中的属性timer
。 timers
数组包含 TimerModel
的实例,用作单元格的数据模型。
哦,对不起。我的错!应该仔细看看。在这种情况下:很好的解决方案!以上是关于当 collectionview 刷新时,CollectionView 单元格的计时器会混淆的主要内容,如果未能解决你的问题,请参考以下文章
带有 TableView 和 CollectionView 的 UiView 不会随机刷新
如何在 CollectionView iOS 中停止自动重新加载和刷新图像
CollectionView 标题在滚动时停止刷新/重新加载数据