Ios CollectionView单元';当collectionview刷新时,s计时器会混淆

Ios CollectionView单元';当collectionview刷新时,s计时器会混淆,ios,swift,timer,uicollectionview,uicollectionviewcell,Ios,Swift,Timer,Uicollectionview,Uicollectionviewcell,我有一个collectionView,每个单元格中都包含计时器。当应用程序启动时,所有计时器都可以正常工作,但是,当我刷新集合视图时,所有计时器都被弄混了,到处都是。我很确定这与之前的计时器没有关闭有关 集合视图的代码: func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { let cell =

我有一个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()
}

我认为你的问题与你的细胞出列有关。因为这背后的原理是现有的单元对象被iOS重用,这可能会导致一些问题

例如,在方法中,您使用countdown1和计时器创建cell1,使用cell2和countdown2(+计时器)创建cell2。重新加载collectionView后,cell1和cell2将被重用,但现在cell1将具有不同的索引路径,因此用于倒计时2,并且还创建了一个新的计时器

这可能会导致一个问题,你的计时器在这个过程中被混淆了,就我在你的代码中所看到的,你也从来没有停止过任何计时器,所以我认为你的假设是正确的。每次重新加载集合视图时,都会创建更多计时器

我的建议是:在每个单元格上创建一个属性,其中包含用于计算倒计时的日期对象。然后只需使用一个计时器,通知所有单元格自行更新其内容。也许你可以用NotificationCenter来做这个。
这(或类似的方法)应该可以帮助您避免维护所有这些计时器的整个问题

您可以在tableview中看到类似的方法;它应该是非常直接的,以适应collectionview@Paulw11谢谢,我太懒了,没有真正创建相同的代码;)这是一种方法。但我仍然会为这个案例寻找一个只有一个计时器的解决方案。我的理由是:由于(据我所知)我们正在处理某些事件(“比赛”)的倒计时,我认为它们应该在1秒的时间间隔内同时变化(不保证有多个计时器),并且不会单独停止/启动。因此,我们不需要为每个单元管理计时器,因为我的代码有一个
计时器
;视图控制器中的属性
计时器
timers
数组包含
TimerModel
的实例,该实例用作单元格的数据模型。哦,对不起。我的错!应该仔细看看。在这种情况下:很好的解决方案!