Reputation: 57
I want to delete the user account and all of its documents in Firestore, but with asynchronous queries, Firebase deletes the account before all documents.
Because of that I get an auth error because when firestorm delete the lasts documents, the user no longer exist.
db.collection("users").document(self.user.uid).collection("sachets").getDocuments() { (QuerySnapshot, err) in
if let err = err{
print("Erreur de lecture : \(err)")
} else {
for document in QuerySnapshot!.documents {
db.collection("users").document(self.user.uid).collection("sachets").document(document.documentID).delete(){ err in
if let err = err {
print(" 🔴 Probleme de suppression des docuemnts \(err)")
} else {
print(" 🔵 Documents supprimés")
}
}
}
}
}
self.user?.delete { error in
if let error = error {
print(" 🔴 Probleme de suppression du compte Utilisateur \(error)")
} else {
print(" 🔵 Utilisateur supprimé")
}
}
Someone can tell me how to do ? thanks
Upvotes: 2
Views: 1320
Reputation: 2792
Alright, I set up a test-project and solve this. You also need to make sure to remove all the data from the user fields. For instance, if you're having name
, age
etc... at the user
node.
First I created a function to fetch the current users uid
:
func currentUser() -> String {
return Auth.auth().currentUser!.uid
}
Then I created a function to remove all the data for the logged in user. This will first remove all the subcollection data and then it will remove the document for the userID
.
To handle asynchronous methods you can use DispatchGroup
to notify when all the asynchronous calls are done.
One side note: Make sure to NEVER force-unwrap a value if you can't 100% guarantee there are documents. Otherwise, your app will likely crash. To solve this either use guard
or if let
to solve this problem.
// Where "user" is the result from currentUser()
func removeData(from user: String) {
db.collection("users").document(user).collection("sachets").getDocuments { (snapshot, error) in
if let error = error {
// Handle error
} else if let documents = snapshot?.documents {
// Using if let to see if there are documents
// Time to delete all the subCollection for the user
self.deleteSubCollectionData(for: user, documents, completion: {
// Once that done, make sure to delete all the fields on the highest level.
self.db.collection("users").document(user).delete(completion: { (error) in
if let error = error {
// Handle error
} else {
// Delete the account
self.deleteAccount()
}
})
})
}
}
}
// This function will remove the subCollectionData
fileprivate func deleteSubCollectionData(for user: String, _ documents: [QueryDocumentSnapshot], completion: @escaping () -> ()) {
let group = DispatchGroup()
documents.forEach({
group.enter()
self.db.collection("users").document(user).collection("sachets").document($0.documentID).delete(completion: { (error) in
if let error = error {
// Handle error
}
group.leave()
})
})
// Once the dispatchGroup is done...
group.notify(queue: .main) {
completion()
}
}
And in the end...
func deleteAccount() {
Auth.auth().currentUser?.delete { (error) in
if let error = error {
print(error)
} else {
print("Deleted account")
}
}
}
If you don't remove all the levels of data, then there still will be data in Firestore.
Upvotes: 2
Reputation: 2591
Your getDocuments()
method is asynchronous, so you should delete the account only after having deleted the documents.
Just put the user?.delete
method inside the getDocuments()
callback
db.collection("users").document(self.user.uid).collection("sachets").getDocuments() { (QuerySnapshot, err) in
if let err = err{
print("Erreur de lecture : \(err)")
} else {
for document in QuerySnapshot!.documents {
db.collection("users").document(self.user.uid).collection("sachets").document(document.documentID).delete(){ err in
if let err = err {
print(" 🔴 Problème de suppression des documents \(err)")
} else {
print(" 🔵 Documents supprimés")
}
}
}
}
self.user?.delete { error in
if let error = error {
print(" 🔴 Problème de suppression du compte Utilisateur \(error)")
} else {
print(" 🔵 Utilisateur supprimé")
}
}
}
Upvotes: 0