Delete NSTimer/UITableViewCell in real time?

2019-04-18 04:08发布

问题:

I have a UITableView in which I have numerous timers set on each UITableViewCell. Each timer starts from when a user creates a "post" on my application and should expire within 24 hours. However, I want it so that when all 24 hours is over, the UITableViewCell deletes itself in real time but I can't seem to figure out where or when I should be deleting the timer. I have a method that will constantly refresh the timer every second using NSTimer.scheduledTimerWithTimeInterval and it updates the timers on each UITableViewCell every second. However, I can't find a method or find how I can find if each timer inside each UITableViewCell is finished. Obviously I can find if the timer is finished in viewDidLoad but that is only called right when the view becomes active. Is there any method I am missing or anything I can use to find if a timer via the scheduledTimerWithTimeInterval method is finished, and if it is, to delete it? Here is my code below:

//I have a self.offers array declared in the beginning of my class whcih will act as the UITableView data source.
var offers = [Offer]()


func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    //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]
    cell.offerName.text = item.offerName()
    cell.offerPoster.text = item.offerPoster()

    var expirDate: NSTimeInterval = item.dateExpired()!.doubleValue

    //Get current time and subtract it by the predicted expiration date of the cell. Subtract them to get the countdown timer.
    var timeUntilEnd = expirDate - NSDate().timeIntervalSince1970

    if timeUntilEnd <= 0 {
        //Here is where I want to delete the countdown timer but it gets difficult to do so when you are also inserting UITableViewCells and deleting them at the same time.
        self.offers.removeAtIndex(indexPath!.row)

        self.offersReference = Firebase(url:"<Database Link>")
        self.offersReference.removeValue()
        self.tableView.reloadData()
        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
    }
}

override func viewDidLoad() {
    super.viewDidLoad()
    var timeExpired = false
    //I set up my offers array above with completion handler
    setupOffers { (result, offer) -> Void in
        if(result == true){
            //Insert each row one by one.
            var currentCount = self.offers.count
            var indexPaths: [NSIndexPath] = [NSIndexPath]()
            indexPaths.append(NSIndexPath(forRow:currentCount, inSection: 0))
            self.offers.append(offer)
            currentCount++
            self.tableView.reloadData()
        }
    }
    // Do any additional setup after loading the view, typically from a nib.
    self.tableView.delegate = self
    self.tableView.dataSource = self
    self.tableView.rowHeight = UITableViewAutomaticDimension
    self.tableView.rowHeight = 145.0
}

//Called when you click on the tab
override func viewDidAppear(animated: Bool) {
    super.viewDidAppear(animated)
    self.refreshTimer = NSTimer.scheduledTimerWithTimeInterval(1.0, target: self, selector: "refreshView:", userInfo: nil, repeats: true)
    //Should fire while scrolling, so we need to add the timer manually:
    //var currentRunLoop = NSRunLoop()
    //currentRunLoop.addTimer(refreshTimer, forMode: NSRunLoopCommonModes)
}

override func viewDidDisappear(animated: Bool) {
    super.viewDidDisappear(animated)
    refreshTimer.invalidate()
    refreshTimer = nil
}

//Constantly refreshes the data in the offers array so that the time will continuously be updating every second on the screen.
func refreshView(timer: NSTimer){
    self.tableView.reloadData()
}

回答1:

You have a number of misconceptions, a few problems with your code, and your description isn't clear.

If you create a timer using scheduledTimerWithTimeInterval, you don't need to, and shouldn't, add it to the runloop. The scheduledTimerWithTimeInterval method does that for you.

If you create a repeating timer, it never "finishes." It keeps repeating forever. If instead you create a non-repeating timer, it fires once and then goes away. You don't need to delete it. Just don't keep a strong reference to it and it will be deallocated once it fires.

You say you create a timer for each table view cell, but the code you posted only creates a single timer for the view controller. You say "...it updates the timers on each UITableViewCell every second. However, I can't find a method or find how I can find if each timer inside each UITableViewCell is finished." That doesn't match the code you posted. Your code is running a timer once a second that simply tells the table view to reload it's data.

I guess you mean that you re-display a remaining time counter in each cell when your timer fires?

So, are you asking how to figure out if the time remaining for all of your cell's item.timeLeft() has reached zero? You haven't posted the code or the requirements for your timeLeft() function, so your readers can't tell what is supposed to be happening.