IOS:使用 NSTimer 更新 UITableViewCell 中的标签
IOS: Updating Labels in a UITableViewCell using an NSTimer
我正在尝试创建一个倒计时应用程序,该应用程序将显示年数....到即将到来的日期为止的秒数。我希望能够在 table 视图中查看多个倒计时。我有一些独立于 table 视图单元格来创建倒计时的基本逻辑:
.
.
.
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)")
}
这很好用,控制台显示倒计时。但是,当我尝试从单元格中调用它时,我无法克服错误。
Terminating app due to uncaught exception
'NSInvalidArgumentException', reason: '-[__NSCFTimer row]:
unrecognized selector sent to instance
这是无效的代码。
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)"
}
感谢您提供的任何帮助。我最初将我的修复尝试集中在改变我从计时器调用 update() 的方式上。我尝试显式传递单元格,然后认为最好尝试调用单元格的 indexPath。我还按照许多 NSTimer 帖子中的建议检查了我的语法。我想我做对了(并且相信我已经尝试了几乎所有其他选项)。
代码在这一行中断:
if let cell = tableView.cellForRowAtIndexPath(cellIndex) { ...
传递给 NSTimer
的 scheduledTimerWithTimeInterval(_:target:selector:userInfo:repeats:)
的选择器接收到 NSTimer
对象,而不是 NSIndexPath
。
也就是说,你的update(_:)
方法应该定义为
func update(timer: NSTimer) {
cellIndex = timer.userInfo as! NSIndexPath
...
}
有关详细信息,请参阅 method's documentation
更简单的方法是保持 运行 你的 nstimer 它是 v 调用倒计时方法并在最后重新加载你的 UITableView。在每次重新加载之前将值显示在 NSArray 中,并将其作为对象传递给 UITableView。
我会推荐一种不同的方法来构建您的应用程序。
UITableView
将使用 dequeueReusableCellWithIdentifier
方法 "recycle" 其单元格。因此,如果用户要使用您的应用程序创建 100 个倒计时,但屏幕上最多只能显示 4 个单元格,当用户滚动时,这四个单元格将排入 table 视图的单元格缓存中,然后由您的数据源代码出列。这样做是为了提高性能,以便 table 视图可以平滑滚动。您可以在 Apple 的 Table View Programming Guide.
中阅读有关此行为的更多信息
如果是我...
我首先拥有一个可以跟踪倒计时状态的对象:倒计时开始日期、倒计时结束日期、倒计时名称等。
我将使用这些对象的数组作为 table 视图表示的数据。
由于 all 倒计时每秒更新一次,您可以通过询问 table 查看当前显示的索引路径来更新当前显示的内容,将这些索引路径与数组中的倒计时对象匹配,然后更改所有不同标签的文本。这意味着您的视图控制器中只有一个 NSTimer
实例负责驱动更新。
还有很多其他可能的方法来构造它,但我认为试图管理许多计时器实例会导致一些白发。
我正在尝试创建一个倒计时应用程序,该应用程序将显示年数....到即将到来的日期为止的秒数。我希望能够在 table 视图中查看多个倒计时。我有一些独立于 table 视图单元格来创建倒计时的基本逻辑:
.
.
.
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)")
}
这很好用,控制台显示倒计时。但是,当我尝试从单元格中调用它时,我无法克服错误。
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFTimer row]: unrecognized selector sent to instance
这是无效的代码。
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)"
}
感谢您提供的任何帮助。我最初将我的修复尝试集中在改变我从计时器调用 update() 的方式上。我尝试显式传递单元格,然后认为最好尝试调用单元格的 indexPath。我还按照许多 NSTimer 帖子中的建议检查了我的语法。我想我做对了(并且相信我已经尝试了几乎所有其他选项)。
代码在这一行中断:
if let cell = tableView.cellForRowAtIndexPath(cellIndex) { ...
传递给 NSTimer
的 scheduledTimerWithTimeInterval(_:target:selector:userInfo:repeats:)
的选择器接收到 NSTimer
对象,而不是 NSIndexPath
。
也就是说,你的update(_:)
方法应该定义为
func update(timer: NSTimer) {
cellIndex = timer.userInfo as! NSIndexPath
...
}
有关详细信息,请参阅 method's documentation
更简单的方法是保持 运行 你的 nstimer 它是 v 调用倒计时方法并在最后重新加载你的 UITableView。在每次重新加载之前将值显示在 NSArray 中,并将其作为对象传递给 UITableView。
我会推荐一种不同的方法来构建您的应用程序。
UITableView
将使用 dequeueReusableCellWithIdentifier
方法 "recycle" 其单元格。因此,如果用户要使用您的应用程序创建 100 个倒计时,但屏幕上最多只能显示 4 个单元格,当用户滚动时,这四个单元格将排入 table 视图的单元格缓存中,然后由您的数据源代码出列。这样做是为了提高性能,以便 table 视图可以平滑滚动。您可以在 Apple 的 Table View Programming Guide.
如果是我...
我首先拥有一个可以跟踪倒计时状态的对象:倒计时开始日期、倒计时结束日期、倒计时名称等。
我将使用这些对象的数组作为 table 视图表示的数据。
由于 all 倒计时每秒更新一次,您可以通过询问 table 查看当前显示的索引路径来更新当前显示的内容,将这些索引路径与数组中的倒计时对象匹配,然后更改所有不同标签的文本。这意味着您的视图控制器中只有一个
NSTimer
实例负责驱动更新。
还有很多其他可能的方法来构造它,但我认为试图管理许多计时器实例会导致一些白发。