IOS:使用NSTimer更新UITableViewCell中的标签

0 uitableview nstimer ios swift

我正在尝试创建一个倒计时应用程序,它将显示年数......秒数,直到即将到来的日期.我希望能够在表格视图中查看多个倒计时.我有一些基本的逻辑,它们独立于tableview单元格来创建倒计时:

.
.
.
var timer = NSTimer.scheduledTimerWithTimeInterval(1, target: self, selector: "countdown", userInfo: nil, repeats: true)

func  countdown() {
    let hourMinuteComponents: NSCalendarUnit =
        NSCalendarUnit.CalendarUnitYear |
        NSCalendarUnit.CalendarUnitMonth |
        NSCalendarUnit.CalendarUnitDay |
        NSCalendarUnit.CalendarUnitHour |
        NSCalendarUnit.CalendarUnitMinute |
        NSCalendarUnit.CalendarUnitSecond
    let timeDifference = userCalendar.components(
        hourMinuteComponents,
        fromDate: NSDate(),
        toDate: date1.enteredDate as NSDate,
        options: nil)
// Sample Output
    println("Year: \(timeDifference.year)")
    println("Month: \(timeDifference.month)")
    println("Day: \(timeDifference.day)")
    println("Hour: \(timeDifference.hour)")
    println("Minute: \(timeDifference.minute)")
    println("Second: \(timeDifference.second)")
}
Run Code Online (Sandbox Code Playgroud)

这很好用,控制台显示倒计时.但是,当我尝试从单元格中调用它时,我无法通过错误.

由于未捕获的异常'NSInvalidArgumentException'而终止应用程序,原因:' - [__ NSCFTimer row]:发送到实例的无法识别的选择器

这是不起作用的代码.

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    println("Index Path: \(indexPath)")
    let cell = tableView.dequeueReusableCellWithIdentifier("countDownCell") as! UITableViewCell
    let cellIndex = indexPath
    var timer = NSTimer.scheduledTimerWithTimeInterval(1, target: self, selector: "update:", userInfo: cellIndex, repeats: true)
    //let secondlabel = cell.viewWithTag(1005) as! UILabel
    //secondlabel.text = "Test"


    return cell

}


func  update(cellIndex: NSIndexPath) {
    let hourMinuteComponents: NSCalendarUnit =
    NSCalendarUnit.CalendarUnitYear |
    NSCalendarUnit.CalendarUnitMonth |
    NSCalendarUnit.CalendarUnitDay |
        NSCalendarUnit.CalendarUnitHour |
        NSCalendarUnit.CalendarUnitMinute |
        NSCalendarUnit.CalendarUnitSecond
    let timeDifference = userCalendar.components(
        hourMinuteComponents,
        fromDate: NSDate(),
        toDate: date1.enteredDate as NSDate,
        options: nil)
    println("Year: \(timeDifference.year)")
    println("Month: \(timeDifference.month)")
    println("Day: \(timeDifference.day)")
    println("Hour: \(timeDifference.hour)")
    println("Minute: \(timeDifference.minute)")
    println("Second: \(timeDifference.second)")


    if let cell = tableView.cellForRowAtIndexPath(cellIndex) {
        let yearlabel = cell.viewWithTag(1000) as! UILabel
        let secondlabel = cell.viewWithTag(1005) as! UILabel!
    }

    secondlabel.text = "\(timeDifference.second)"


}
Run Code Online (Sandbox Code Playgroud)

我感谢您提供的任何帮助.我最初把我的修复尝试集中在改变我从计时器调用update()的方式.我尝试显式传递单元格然后认为最好尝试调用单元格的indexPath.我也按照许多NSTimer帖子中的建议检查了我的语法.我认为我做得对(并且相信我已经尝试了很多其他选项).

代码在此行中断:

if let cell = tableView.cellForRowAtIndexPath(cellIndex) { ...
Run Code Online (Sandbox Code Playgroud)

ede*_*y05 7

我会推荐一种不同的方法来构建你的应用程序.

UITableView将使用该dequeueReusableCellWithIdentifier方法"回收"其细胞.因此,如果用户要使用您的应用程序创建100个倒计时,但屏幕上最多只能看到4个单元格,当用户滚动时,这四个单元格将被排入表格视图的单元格缓存中,然后由您的数据出列源代码.这样做是为了提高性能,使表格视图平滑滚动.您可以在Apple的" 表视图编程指南"中阅读有关此行为的更多信息.

如果是我......

  1. 我首先要有一个可以跟踪倒计时状态的对象:倒计时开始日期,倒计时结束日期,倒计时名称等.

  2. 我将使用这些对象的数组作为表视图表示的数据.

  3. 由于所有倒计时每秒都会更新,因此您可以通过询问表格视图当前显示的索引路径,将这些索引路径与阵列中的倒计时对象匹配,然后更改所有不同标签的文本来更新当前显示的内容.这意味着您NSTimer的视图控制器中只有一个实例负责驱动更新.

有很多其他可能的方法来构建它,但我认为尝试管理许多计时器实例会导致一些白发.

  • @ edlaney05我太新了,无法对你的指导进行投票,但我整理了一个在viewdidload()上实例化的计时器,然后使用:`let cells = tableView.indexPathsForVisibleRows()as Array!``for i in cells` I能够用一个计时器更新数据 (2认同)