NSTimer inside custom tableViewCell

2020-04-30 07:24发布

问题:

I'm activating a function in my custom cell class from a viewController. The custom cell class looks like this:

import UIKit

class TableViewCell: UITableViewCell {

    var counter = 10

    class func timerStarted(){
        var timer = NSTimer()

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

    class func update(){

        let cell = TableViewCell()
        var count = cell.counter
        count = --count
        println(counter)
    }
}

The problem is that the variable counter does not change, so 9 is printed every interval. How do I make it so that it changes value every time and counts down?

Any suggestions would be appreciated.

EDIT: I'm using a long press gesture recognizer to trigger the function, which is the reason I can't just trigger it using a didSelectRowAtIndexPath-function. My code for the long press looks like this:

func longPressActive(gestureRecognizer:UIGestureRecognizer) {
    if (gestureRecognizer.state == UIGestureRecognizerState.Began) {
        var point = gestureRecognizer.locationInView(self.tv)
        if let indexPath = self.tv.indexPathForRowAtPoint(point) {
            TableViewCell.timerStarted()
        }
    }
}

回答1:

Alright, so your problem is that you are calling a class method on the TableView class rather than an instance function. You want to get a handle on an actual cell instance, not just the class. So first, your TableCell class with the proper signatures (i.e. remove the class prefix):

class TableViewCell: UITableViewCell {

    var counter = 10

    // No longer class functions! :)
    func timerStarted(){
        var timer = NSTimer()

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

    func update() {
        // Update counter
        counter-- // <-- performs the actual decrement for you
        println(counter)
    }
}

Then just update your long press to activate the timer on an actual cell, not just the cell's class:

func longPressActive(gestureRecognizer:UIGestureRecognizer) {
    if (gestureRecognizer.state == UIGestureRecognizerState.Began) {
        var point = gestureRecognizer.locationInView(self.tv)
        if let indexPath = self.tv.indexPathForRowAtPoint(point) {
            // Check to make sure it is the correct subclass
            if let cell = self.tv.cellForRowAtIndexPath(indexPath: indexPath) as? TableViewCell {
                // Starting the timer on the actual cell, not just the cell class
                cell.timerStarted();
            }
        }
    }
}

Also, I want to make a comment about your timerStarted() function. You first create a new timer and assign it to timer and then you create a second timer and assign that to timer as well, redundant. Also, since you are not saving the timer outside that method there is no need to create a variable (to keep your same functionality). So the function could be:

func timerStarted(){
    NSTimer.scheduledTimerWithTimeInterval(1, target: self, selector: "update", userInfo: nil, repeats: true)
}

But there is a good chance you will want to cancel this at some point, so I would probably store it as an instance variable:

private var timer: NSTimer

func timerStarted(){
    self.timer = NSTimer.scheduledTimerWithTimeInterval(1, target: self, selector: "update", userInfo: nil, repeats: true)
}


回答2:

override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
    let cell = tableView.cellForRowAtIndexPath(indexPath) as TableViewCell
    cell.timerStarted()
}

For your tableview cell class:

func timerStarted(){
    var timer = NSTimer()

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

func update(){
    counter = counter - 1
    println(counter)
}