我有一个NSTimer,我想实时更新标签,显示计时器的时间。以下是我实现的方式:
override func viewDidAppear(animated: Bool) {
self.refreshTimer = NSTimer.scheduledTimerWithTimeInterval(1.0, target: self, selector: "refreshView:", userInfo: nil, repeats: true)
var currentRunLoop = NSRunLoop()
currentRunLoop.addTimer(refreshTimer, forMode: NSRunLoopCommonModes)
}
func refreshView(timer: NSTimer){
for cell in self.tableView.visibleCells(){
var indexPath = self.tableView.indexPathForCell(cell as! UITableViewCell)
self.tableView(self.tableView, cellForRowAtIndexPath: indexPath!)
}
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
return offerCellAtIndexPath(indexPath)
}
func offerCellAtIndexPath(indexPath: NSIndexPath) -> OfferCell{
//Dequeue a "reusable" cell
let cell = tableView.dequeueReusableCellWithIdentifier(offerCellIdentifier) as! OfferCell
setCellContents(cell, indexPath: indexPath)
return cell
}
func setCellContents(cell:OfferCell, indexPath: NSIndexPath!){
let item = self.offers[indexPath.row]
var expirDate: NSTimeInterval = item.dateExpired()!.doubleValue
var expirDateServer = NSDate(timeIntervalSince1970: expirDate)
//Get current time and subtract it by the predicted expiration date of the cell. Subtract them to get the countdown timer.
var timer = self.modelStore[indexPath.row] as! Timer
var timeUntilEnd = timer.endDate.timeIntervalSince1970 - NSDate().timeIntervalSince1970
if timeUntilEnd <= 0 {
cell.timeLeft.text = "Finished."
}
else{
//Display the time left
var seconds = timeUntilEnd % 60
var minutes = (timeUntilEnd / 60) % 60
var hours = timeUntilEnd / 3600
cell.timeLeft.text = NSString(format: "%dh %dm %ds", Int(hours), Int(minutes), Int(seconds)) as String
}
}
正如代码所示,我尝试执行以下操作:
dispatch_async(dispatch_get_main_queue(), { () -> Void in
cell.timeLeft.text = NSString(format: "%dh %dm %ds", Int(hours), Int(minutes), Int(seconds)) as String
})
我认为这会帮助我实时更新单元格,但是当我查看单元格时,它们并没有实时更新。当我打印出seconds
,minutes
和hours
时,它们每1秒更新一次,这是正确的。但是,标签只是没有更新。关于如何做到这一点的任何想法?
if timeUntilEnd <= 0 {
//Countdown is done for timer so delete it.
self.offers.removeAtIndex(indexPath!.row)
self.tableView.deleteRowsAtIndexPaths([indexPath!], withRowAnimation: UITableViewRowAnimation.Fade)
self.tableView.reloadRowsAtIndexPaths([indexPath], withRowAnimation: UITableViewRowAnimation.Fade)
cell.timeLeft.text = "Finished."
}
答案 0 :(得分:0)
这很疯狂:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
return offerCellAtIndexPath(indexPath)
}
func offerCellAtIndexPath(indexPath: NSIndexPath) -> OfferCell{
//Dequeue a "reusable" cell
let cell = tableView.dequeueReusableCellWithIdentifier(offerCellIdentifier) as! OfferCell
setCellContents(cell, indexPath: indexPath)
return cell
}
您在cellForRowAtIndexPath:
的工作是返回单元格 - now 。但是setCellContents
不会将任何单元格返回offerCellAtIndexPath
,因此返回的单元格只是第一行的空的OfferCell。此外,setCellContents
无法返回任何单元格,因为它包含async
,只有在返回之后才能运行。
您需要首先启动此三重呼叫架构,然后在cellForRowAtIndexPath:
中返回实际单元格 now 。然后你可以担心定时更新是一个完全独立的问题。
答案 1 :(得分:0)
您可以使用调度计时器:
class func createDispatchTimer(
interval: UInt64,
leeway: UInt64,
queue: dispatch_queue_t,
block: dispatch_block_t) -> dispatch_source_t?
{
var timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue)
if timer != nil
{
dispatch_source_set_timer(timer, dispatch_walltime(nil, 0), interval, leeway)
dispatch_source_set_event_handler(timer, block)
return timer!
}
return nil
}