swifttimernstimerdispatch-asyncdispatchertimer

How to set timer in one vc and fire it in another vc


my goal is to set a timer in one vc when a firestore document is created and fire it in another vc when the timer is up to delete the firestore document.

In my vc where I create the document, I have this block of code in the button that creates the document in firestore:

db.collection("school_users/\(user?.uid)/events").addDocument(data: ["event_name": nameTextField.text, "event_date": dateTextField.text, "event_cost": costTextField.text, "for_grades": gradesTextField.text, "school_id": schoolIDTextF.text, "time_created": Date()]) { (error) in
                if error != nil {
                    self.showError("There was an error trying to add user data to the system.")
                } else {
                    self.setTimerForEventDeletion()
                    self.dismiss(animated: true, completion: nil)
                }
            }

The setTimerForEventDeletion() function contains this :

  func setTimerForEventDeletion() {
    let date = dateTextField.text!
   let dateToDelete = formatter.date(from: date)!
    let timer = Timer(fireAt: dateToDelete, interval: 0, target: self, selector: #selector(callDeleteEventFunction), userInfo: nil, repeats: false)
    
}

The date format is correct as well I already have all that setup. For the objc method, I call another function from a different vc (will explain) in that function.

 @objc func callDeleteEventFunction() {
    otherVC.deleteEventAtEventTime()
}

The reason I call this function from the other vc is because the other vc is storing the details of the created document, you can't fetch the details of a document that isn't created yet, so I have it in another VC. The function looks like this...

@objc func deleteEventAtEventTime() {
    db.document("school_users/\(user?.uid)/events/\(selectedEventDocID!)").delete { (error) in
        if let error = error {
            print("There was an error deleting the doc: \(error)")
        } else {
            print("Doc deleted!")
        }
    }

}

Now before posting this question, I tested it by firing the timer in the same vc that stores the document details and it worked, but when I exited that vc, the cell deleted and the tableview shrank, basically glitching out the app, and eventually crashed when I clicked another cell with different details.

So i want to be able to have the timer be set when the document is created in one vc, and have the timer fire in another vc when the deletion date arrives.


Solution

  • After doing some research and reading around, I've figured it's best to use Googe Cloud Functions to perform the task of auto-deletion of a Firestore document in a database as well as in my app.

    After doing some even more research, I realized that going through this wasn't necessary at least for now. I will provide a very simple workaround that took about 20 minutes to figure out and prevented me from having to learn Node to do Cloud Functions.

    So what I wanted to get done was be able to delete documents when they expire automatically and I got that done with a couple blocks of code.

    So first, I declared 2 variables to help with formatting.

    let rightNow = Date()
    let formatter = DateFormatter()
    

    These will help with the next function I'm about to show.

      func setupDate(completion: @escaping ((String?) -> ())) {
        formatter.dateFormat = "EEEE, MMMM d yyyy, h:mm a"
       let dateToString = formatter.string(from: rightNow)
        completion(dateToString)
    }
    

    This function gave me the date as a String so I could put it inside my query function which I will show as well. I used nsdateformatter.com to get the exact format I had in my textfield, I recommend using that site for Date() related code in regards to formatting.

    This next function basically sealed the deal and is the reason why everything works.

    func deleteExpiredCreatedEvents() {
        setupDate { (dateforexpiry) in
                self.db.collection(Constants.Firebase.schoolCollectionName).whereField("expiresAt", isLessThanOrEqualTo: dateforexpiry!).addSnapshotListener { (querySnapshot, error) in
                    if error != nil {
                        print("Error fetching docs/User deleted account.")
                    } else {
                        for document in querySnapshot!.documents {
                            let documentident = document.documentID
                            let docalgoliaid = document.get("algoliaObjectID") as! String
                            
                            deleteIndex.deleteObject(withID: ObjectID(rawValue: docalgoliaid)) { (result) in
                                if case .success(let response) = result {
                                    print("Record Deleted!: \(response.wrapped)")
                                }
                            }
    
                            self.db.document("school_users/\(self.user?.uid)/events/\(documentident)").delete { (err) in
                                if err != nil {
                                    print("Errr")
                                } else {
                                    print("No errs")
                                    self.tableView.reloadData()
                                }
                            }
                        }
                    }
                }
        }
    }
    

    I then call this function in the viewDidLoad() of the desired vc and the events loaded are only the ones not expired. Hope this can shine some light on somebody in the future having trouble with the same issue.