我的目标是为timer
中每个已填充的uicollectionviewcell
设置一个唯一的(hh:mm:ss)倒计时uicollectionview
。
以下是我已经能够编译的(缩写)代码,但我仍坚持让它真正以任何身份工作......任何指导都将不胜感激。
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...
}
}
}
答案 0 :(得分:1)
不会不断更新集合视图单元格。如果您希望它们更新,您必须告诉他们更新。
如果希望每个单元格显示不同的剩余时间,则需要一个数据模型,为您显示的每个indexPath保存单独的expirationDate
。如果您的集合视图是一个简单的一维项目列表,如表格视图,那么您可以使用一维数组。如果您的集合视图显示单元格网格,则可能需要二维模型对象数组。
每次向数据模型添加项目时,都要包含expirationDate
值。 (当该项目到期时Date
。)
然后让你的计时器每次触发时调用集合视图的reloadData
方法。
在collectionView(collectionView:cellForItemAt:)
方法中,使用indexPath确定要显示的数据模型中的哪个项目。查找该indexPath的expirationDate
,计算从现在到到期日期的剩余时间,并在单元格中显示该信息。 (使用Calendar
方法dateComponents(_:from:to:)
计算从现在到您的到期日期之间的小时数,分钟数和秒数。)
不要递减计数器。使用dateComponents(_:from:to:)
示例集合视图控制器可以执行以下操作:
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
}
}
上面的代码如下所示: