NSTimer实时更新?

时间:2015-04-30 16:11:49

标签: ios swift timer real-time nstimer

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

我认为这会帮助我实时更新单元格,但是当我查看单元格时,它们并没有实时更新。当我打印出secondsminuteshours时,它们每1秒更新一次,这是正确的。但是,标签只是没有更新。关于如何做到这一点的任何想法?

编辑:DuncanC的回答帮助了很多人。我想在他们的计时器转到0时也删除计时器。但是,我收到一个错误,说当你删除和插入极有可能非常快,而不给任何时候加载表视图时有一个不一致。这是我的主张:

    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."
    }

2 个答案:

答案 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
}