Chris
Chris

Reputation: 387

Removing rows from Tableview after time expires

I have searched every source I know of for help on this problem. I want to make individual rows within a tableview disappear after a certain amount of time expires. Even if the app is not open, I want the rows to delete as soon as the timer reaches zero. I have been trying to arrange each post into an dictionary with timer pairings to handle the row deletion when time occurs. I have looked at this post for guidance but no solutions. Swift deleting table view cell when timer expires.

This is my code for handling the tableview and the timers:

var nextID: String?
var postsInFeed = [String]()
var postTimer = [Timer: String]()
var timeLeft = [String: Int]()

(in view did load)

DataService.ds.REF_FEED.observe(.value, with: { (snapshot) in
        self.posts = []
        self.postsInFeed = []
        self.nextID = nil

        if let snapshot = snapshot.children.allObjects as? [DataSnapshot] { //Gets us into our users class of our DB
            for snap in snapshot { // Iterates over each user
                if let postDict = snap.value as? Dictionary<String, Any> { // Opens up the dictonary key value pairs for each user.
                    let key = snap.key //
                    let post = Post(postID: key, postData: postDict) // Sets the properties in the dictionary to a variable.
                    self.posts.append(post) // appends each post which contains a caption, imageurl and likes to the empty posts array.


                    self.nextID = snap.key
                    let activeID = self.nextID
                    self.postsInFeed.append(activeID!)

                    print(self.postsInFeed)
                    print(activeID!)


                }

            }

        }
        self.tableView.reloadData()

    })

//////////////////////////////////////////////////////////////////////////////////////////////
// Sets up our tableview
func numberOfSections(in tableView: UITableView) -> Int {
    return 1
}

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return postsInFeed.count
}


func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

    let post = posts[indexPath.row] // We get our post object from the array we populate when we call the data from the database up above.

    if let cell = tableView.dequeueReusableCell(withIdentifier: "tableCell") as? TableViewCell { //Specifies the format of the cell we want from the UI

// cell.cellID = self.postsInFeed[indexPath.row]

        cell.cellID = self.postsInFeed[indexPath.row]


        cell.homeVC = self


        if let img = HomeVC.imageCache.object(forKey: post.imageUrl as NSString){
            cell.configureCell(post: post, img: img as? UIImage)
            print(postTimer)
            print(self.timeLeft)

        }  else {

            cell.configureCell(post: post)
            print(postTimer)
            print(self.timeLeft)
        }


        return cell


    } else {
        return TableViewCell()
    }
}

    func handleCountdown(timer: Timer) {
    let cellID = postTimer[timer]

    // find the current row corresponding to the cellID
    let row = postsInFeed.index(of: cellID!)

    // decrement time left
    let timeRemaining = timeLeft[(cellID!)]! - 1
    timeLeft[cellID!] = timeRemaining
    if timeRemaining == 0 {
        timer.invalidate()

        postTimer[timer] = nil
        postsInFeed.remove(at: row!)
        tableView.deleteRows(at: [IndexPath(row: row!, section: 0)], with: .fade)

    } else {
        tableView.reloadRows(at: [IndexPath(row: row!, section: 0)], with: .fade)
    }
}

In the tableviewcell:

weak var homeVC: HomeVC?
var cellID: String!

    func callTime() {
    homeVC?.timeLeft[cellID] = 25
    let timer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(homeVC?.handleCountdown(timer:)), userInfo: nil, repeats: true)
    homeVC?.postTimer[timer] = cellID

}

Any help would be really appreciated!

Upvotes: 0

Views: 217

Answers (1)

Duncan C
Duncan C

Reputation: 131408

Timers don't run when your app is not running or is suspended.

You should rework your code to save a date (to UserDefaults) when you start your timer, and then each time the timer fires, compare the current date to the saved date. Use the amount of elapsed time to decide how many entries in your table view's data model to delete. (In case more than one timer period elapsed while you were suspended/not running.)

You should implement applicationDidEnterBackground() in your app delegate (or subscribe to the equivalent notification, UIApplicationDidEnterBackground) and stop your timer(s).

Then implement the app delegate applicationDidBecomeActive() method (or add a notification handler for the UIApplicationDidBecomeActive notification), and in that method, check the amount of time that has elapsed, update your table view's data model, and tell the table view to reload if you've removed any entries. Then finally restart your timer to update your table view while your app is running in the foreground.

Upvotes: 0

Related Questions