Ios 在UICollectionViewCell中添加带计时器的倒计时标签的最佳方法,即使在重复使用单元格后也可以正常工作
我有一个在Ios 在UICollectionViewCell中添加带计时器的倒计时标签的最佳方法,即使在重复使用单元格后也可以正常工作,ios,swift,swift3,timer,uicollectionviewcell,Ios,Swift,Swift3,Timer,Uicollectionviewcell,我有一个在UICollectionView中呈现给用户的项目列表。这些项目具有倒计时标签,以显示项目可用的剩余时间。 我在UICollectionViewCell中使用了计时器来显示剩余时间,如: OperationQueue.main.addOperation { var remaingTimeInterval = self.calculateRemainigTime(remainingTime: remainingTime) if remaingTimeInt
UICollectionView
中呈现给用户的项目列表。这些项目具有倒计时标签,以显示项目可用的剩余时间。
我在UICollectionViewCell
中使用了计时器
来显示剩余时间,如:
OperationQueue.main.addOperation {
var remaingTimeInterval = self.calculateRemainigTime(remainingTime: remainingTime)
if remaingTimeInterval > 0 {
self.timerLabel.isHidden = false
self.timer = Timer.scheduledTimer(withTimeInterval: 1, repeats: true, block: { [weak self] (_) in
let hours = Int(remaingTimeInterval) / 3600
let minutes = Int(remaingTimeInterval) / 60 % 60
let seconds = Int(remaingTimeInterval) % 60
self?.timerLabel?.text = String(format:"%02i:%02i:%02i", hours, minutes, seconds)
remaingTimeInterval -= 1
})
} else {
self.timer?.invalidate()
self.timerLabel.isHidden = true
}
}
这就是我根据给定日期计算剩余时间的方法:
//Calculating remaining time based on the item endDate and currentDAte
func calculateRemainigTime(remainingTime: String) -> Int {
let prizeRemainingTime = Helper.stringToDate(remainingTime)
let prizeRemainingTimeInterval = Int(prizeRemainingTime.timeIntervalSince1970)
let currentTimeInterval = Int(Date().timeIntervalSince1970)
return prizeRemainingTimeInterval - currentTimeInterval
}
在重新使用电池之前,一切都正常,此后倒计时数字不再正确
这是在UICollectionViewCell中显示倒计时的正确方法,还是有更好的解决方案
有人能帮我找到一种解决方法吗?我实现了这种更简单的方法(不考虑性能/延迟) 在..cellForItemAt。。方法,我打电话
cell.localEndTime = yourEndTimeInterval
cell.startTimerProgress()
在“集合视图”单元中,我添加了一个启动进度的方法:
var localEndTime: TimeInterval = 0 //set value from model
var timer:Timer?
func timerIsRunning(timer: Timer){
let diff = localEndTime - Date().timeIntervalSince1970
if diff > 0 {
self.showProgress()
return
}
self.stopProgress()
}
func showProgress(){
let endDate = Date(timeIntervalSince1970: localEndTime)
let nowDate = Date()
let components = Calendar.current.dateComponents(Set([.day, .hour, .minute, .second]), from: nowDate, to: endDate)
self?.timerLabel?.text = String(format:"%02i:%02i:%02i", components.hour!, components.minute!, components.second!)
}
func stopProgress(){
self?.timerLabel?.text = String(format:"%02i:%02i:%02i", 0, 0, 0)
self.timer?.invalidate()
self.timer = nil
}
func startTimerProgress() {
timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(self.timerIsRunning(timer:)), userInfo: nil, repeats: true)
self.timer?.fire()
}
我实现了这种更简单的方法(不考虑性能/延迟) 在..cellForItemAt。。方法,我打电话
cell.localEndTime = yourEndTimeInterval
cell.startTimerProgress()
在“集合视图”单元中,我添加了一个启动进度的方法:
var localEndTime: TimeInterval = 0 //set value from model
var timer:Timer?
func timerIsRunning(timer: Timer){
let diff = localEndTime - Date().timeIntervalSince1970
if diff > 0 {
self.showProgress()
return
}
self.stopProgress()
}
func showProgress(){
let endDate = Date(timeIntervalSince1970: localEndTime)
let nowDate = Date()
let components = Calendar.current.dateComponents(Set([.day, .hour, .minute, .second]), from: nowDate, to: endDate)
self?.timerLabel?.text = String(format:"%02i:%02i:%02i", components.hour!, components.minute!, components.second!)
}
func stopProgress(){
self?.timerLabel?.text = String(format:"%02i:%02i:%02i", 0, 0, 0)
self.timer?.invalidate()
self.timer = nil
}
func startTimerProgress() {
timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(self.timerIsRunning(timer:)), userInfo: nil, repeats: true)
self.timer?.fire()
}
- 将计时器逻辑移到数据模型
- 使用
定时器的基于块的API来代替目标/动作
- 在
中,将计时器回调块传递给单元格cellForRow
- 当计时器触发时,回调块中的代码可以更新单元格中的UI
- 将计时器逻辑移到数据模型
- 使用
定时器的基于块的API来代替目标/动作
- 在
中,将计时器回调块传递给单元格cellForRow
- 当计时器触发时,回调块中的代码可以更新单元格中的UI
protocol MyViewControllerDelegate : class {
func updateTimer(_ timeString: String)
}
class MyViewController: UIViewController {
weak var timerDetegate: MyViewControllerDelegate?
var timer = Timer()
var time = 0
fun ViewDidLoad() {
timer = Timer.scheduledTimer(withTimeInterval: 1, repeats: true, block: { _ in
self.time += 1
self.timerDetegate?.updateTimer("time \(self.time)")
})
}
...
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableViewdequeueReusableCell(withIdentifier: "MeCell")
vc.timerDetegate = cell
return cell
}
...
}
MyTableViewCell
class MyTableViewCell : UITableViewCell, MyViewControllerDelegate {
...
func updateTimer(_ timeString: String) {
lblTimeLeft.text = timeString
}
}
根据公认的答案指南编码,希望您喜欢 MyViewController
protocol MyViewControllerDelegate : class {
func updateTimer(_ timeString: String)
}
class MyViewController: UIViewController {
weak var timerDetegate: MyViewControllerDelegate?
var timer = Timer()
var time = 0
fun ViewDidLoad() {
timer = Timer.scheduledTimer(withTimeInterval: 1, repeats: true, block: { _ in
self.time += 1
self.timerDetegate?.updateTimer("time \(self.time)")
})
}
...
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableViewdequeueReusableCell(withIdentifier: "MeCell")
vc.timerDetegate = cell
return cell
}
...
}
MyTableViewCell
class MyTableViewCell : UITableViewCell, MyViewControllerDelegate {
...
func updateTimer(_ timeString: String) {
lblTimeLeft.text = timeString
}
}
更好的解决方案是在数据模型中而不是在视图中运行计时器。你是什么意思?是否在数据模型中添加属性以节省剩余时间?那么如何每秒更新它呢?例如,您可以在模型中运行计时器,并将
cellForRow
中的操作或回调传递给cell。我认为这不起作用,因为cellForRow
仅在要重用cell时才被调用,但是我必须每秒钟显示一次倒计时。为了让它更清楚:您使用基于块的APITimer
,并将cellForRow
中的块传递给单元格。只要计时器启动时单元格可见,它就会调用更新UI的块。更好的解决方案是在数据模型中而不是在视图中运行计时器。你是什么意思?是否在数据模型中添加属性以节省剩余时间?那么如何每秒更新它呢?例如,您可以在模型中运行计时器,并将cellForRow
中的操作或回调传递给cell。我认为这不起作用,因为cellForRow
仅在要重用cell时才被调用,但是我必须每秒钟显示一次倒计时。为了让它更清楚:您使用基于块的APITimer
,并将cellForRow
中的块传递给单元格。只要计时器触发时单元格可见,它就会调用更新UI的块。