I'm trying to create a countdown app that will show the number of Years....Seconds until an upcoming date. I want to be able to view several countdowns in a table view. I have some basic logic that works idependently of a tableview cell to create the countdown:
.
.
.
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)")
}
This works well and the console shows the countdown. However, I can't get past an error when I try to call it from a cell.
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFTimer row]: unrecognized selector sent to instance
Here's the code that isn't working.
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)"
}
I appreciate any help you can provide. I initially focused my fixing attempts on changing how I'm calling update() from the timer. I tried passing the cell explicitly and then thought it better to try calling the indexPath of the cell. I also checked my syntax as was suggested in a number of NSTimer posts. I think I have it right (and believe I've tried pretty much all other options).
The code breaks at this line:
if let cell = tableView.cellForRowAtIndexPath(cellIndex) { ...
The selector passed to NSTimer
's scheduledTimerWithTimeInterval(_:target:selector:userInfo:repeats:)
receives a NSTimer
object, not a NSIndexPath
.
That is, your update(_:)
method should be defined as
func update(timer: NSTimer) {
cellIndex = timer.userInfo as! NSIndexPath
...
}
See the method's documentation for more information