ios - 向 UICollectionView 添加多个倒数计时器

标签 ios swift timer uicollectionview uicollectionviewcell

我的目标是有一个独特的 (hh:mm:ss) 倒计时 timer对于每个填充的 uicollectionviewcelluicollectionview 内.

下面是我能够编译的(缩写的)代码,但我坚持让它以任何身份真正工作......任何指导将不胜感激。

class VC: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate {

var timer = Timer()
var secondsRemaining: Int?

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier, for: indexPath as IndexPath) as! ExampleCollectionViewCell    

    let expirationDate = Calendar.current.date(byAdding: .hour, value: 24, to: startDate)
    secondsRemaining = expirationDate?.seconds(from: startDate)

    timer = Timer(timeInterval: 1, target: self, selector: #selector(countdown), userInfo: nil, repeats: true)

    return cell
}

    @objc func countdown() {
    secondsRemaining = secondsRemaining! - 1
    if secondsRemaining == 0 {
        print("CELL TIME HAS EXPIRED!")
        timer.invalidate()
    } else {
        let hours = secondsRemaining! / 3600
        let minutes = (secondsRemaining! % 3600) / 60
        let seconds = (secondsRemaining! % 3600) % 60
        let countdownLabelString = String(format: "%02d:%02d:%02d", hours, minutes, seconds)

        //i need to take this countdownLabelString and set it to the 
        //countdownLabel.text that is an element of each cell. i tried 
        //doing all of this in the cell subclass, but no luck... 
    }
} 
}

最佳答案

Collection View 单元格不会不断更新。如果你想让他们更新,你必须告诉他们更新。

如果您希望每个单元格显示不同的剩余时间,您需要一个数据模型,为您显示的每个 indexPath 保存一个单独的 expirationDate。如果您的 Collection View 是一个简单的一维项目列表,例如 TableView ,那么您可以只使用一维数组。如果您的 Collection View 显示单元格网格,您可能需要一个二维模型对象数组。

每次将项目添加到数据模型时,都包含一个 expirationDate 值。 (该项目过期的日期。)

然后让您的计时器在每次触发时调用 Collection View 的 reloadData 方法。

在您的 collectionView(collectionView:cellForItemAt:) 方法中,使用 indexPath 确定要显示的数据模型中的项目。查找该 indexPath 的 expirationDate,计算从现在到到期日期的剩余时间,并在单元格中显示该信息。 (使用 Calendar 方法 dateComponents(_:from:to:) 计算从现在到到期日期之间的小时数、分钟数和秒数。)

编辑

不要每次计时器触发时都递减计数器。使用 dateComponents(_:from:to:)

计算您的到期日期和当前日期之间的差异

编辑#2:

下面是一个示例 Collection View Controller ,它可以执行您想要的操作:

import UIKit

private let reuseIdentifier = "aCell"

class DatesCollectionVC: UICollectionViewController {

    weak var timer: Timer?
    var dates: [Date] = []
    lazy var componentsFormatter: DateComponentsFormatter = {
        let formatter = DateComponentsFormatter()
        formatter.allowedUnits = [.hour, .minute, .second]
        return formatter
    }()

        
    override func viewDidLoad() {
        
        super.viewDidLoad()

        for _ in 1...100 {
            let interval = Double(arc4random_uniform( 10000)) + 120
            dates.append(Date().addingTimeInterval(interval))
        }

        timer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { timer in
            self.collectionView?.reloadData()
        }
    }
    
    // MARK: - UICollectionViewDataSource

    override func numberOfSections(in collectionView: UICollectionView) -> Int {
        return 1
    }


    override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return dates.count
    }

    override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier, for: indexPath) as? MyCell else {
            return UICollectionViewCell()
        }
        
        let now = Date()
        let expireDate = dates[indexPath.row]
        guard  expireDate > now else {
            cell.intervalLabel.text = "00"
            return cell
        }
        
        let desiredComponents: Set<Calendar.Component> = [.hour, .minute, .second]
        let components = Calendar.current.dateComponents(desiredComponents, from: now, to: expireDate)
        cell.intervalLabel.text = self.componentsFormatter.string(from: components)

        return cell
    }
}

上面的代码是这样的:

enter image description here

关于ios - 向 UICollectionView 添加多个倒数计时器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50011472/

相关文章:

ios - 如何仅从 UICollectionView 重新加载更新的单元格

c++ - 将未知长度数组从 c 返回到结构体中的 Swift

ios - parse.com/iOS - 有没有办法以 json 格式下载整个类对象?

javascript - 如何将 javascript 计时器集成到倒计时以从 ruby​​ 变量进行计数?

c# - Windows 窗体在显示消息前等待 5 秒

ios - 防止键盘在插入 View Controller 时消失

iphone - 我怎样才能区分 UITableViewCell 的哪一部分被点击了

ios - UIImageView 在 iOS6 上不显示

swift - 一对 DatePickers SwiftUI

c# - 在 WinForm 上运行数字时钟