【发布时间】:2021-04-27 16:52:21
【问题描述】:
所以我的目标是在用户删除其帐户时,如果已购买门票的客人数量超过 1,则删除所有用户的客人。
目前我有这个功能来尝试完成这个:
func deleteUserGuests(completion: @escaping (_ done: Bool) -> Void) {
var retries = 0
guard let user = Auth.auth().currentUser else { return }
func checkForGuestsAndDeleteIfAny() {
db.collection("student_users/\(user.uid)/events_bought").getDocuments { (querySnapshot, error) in
if let snapshot = querySnapshot {
if snapshot.isEmpty {
completion(true)
// done, nothing left to delete
} else {
// delete the documents using a dispatch group or a Firestore batch delete
for document in querySnapshot!.documents {
let docID = document.documentID
self.db.collection("student_users/\(user.uid)/events_bought/\(docID)/guests").getDocuments { (querySnap, error) in
guard querySnap?.isEmpty == false else {
print("The user being deleted has no guests with his purchases.")
return
}
let group = DispatchGroup()
for doc in querySnap!.documents {
let guest = doc.documentID
group.enter()
self.db.document("student_users/\(user.uid)/events_bought/\(docID)/guests/\(guest)").delete { (error) in
guard error == nil else {
print("Error deleting guests while deleting user.")
return
}
print("Guests deleted while deleting user!")
group.leave()
}
}
}
}
checkForGuestsAndDeleteIfAny()// call task again when this finishes
// because this function only exits when there is nothing left to delete
// or there have been too many failed attempts
}
} else {
if let error = error {
print(error)
}
retries += 1 // increment retries
run() // retry
}
}
}
func run() {
guard retries < 30 else {
completion(false) // 5 failed attempts, exit function
return
}
if retries == 0 {
checkForGuestsAndDeleteIfAny()
} else { // the more failures, the longer we wait until retrying
DispatchQueue.main.asyncAfter(deadline: .now() + Double(retries)) {
checkForGuestsAndDeleteIfAny()
}
}
}
run()
}
我提高了重试限制,看看是否是问题所在,但如果客人超过一个,它仍然不会删除。
当用户在删除其帐户之前成功重新验证时,我会在警报操作中调用它:
let deleteAction = UIAlertAction(title: "Delete", style: .destructive) { (deletion) in
self.deleteButton.isHidden = true
self.loadingToDelete.alpha = 1
self.loadingToDelete.startAnimating()
self.deleteUserGuests { (response) in
if response == false {
return
}
}
self.deleteUserPurchases { (purchase) in
if purchase == false {
return
}
}
self.deleteUserOutOfFirestore { (removed) in
if removed == false {
return
}
}
user.delete(completion: { (error) in
guard error == nil else {
print("There was an error deleting user from the system.")
return
}
print("User Deleted.")
})
self.loadingToDelete.stopAnimating()
self.performSegue(withIdentifier: Constants.Segues.studentUserDeletedAccount, sender: self)
}
这是数据库中的结果:
其他所有内容都会被删除以正确的顺序、购买、用户本身,然后是用户退出 Firebase 身份验证,但访客永远不会被删除超过 1 位客人。 deleteUserGuests 方法中是否有我做错或遗漏的事情导致了这个问题?
【问题讨论】:
-
你为什么不嵌套这些任务,以便一个接一个地开始,然后在最后一个任务中删除用户对象,然后在完成处理程序中停止动画微调器并继续用户?或者这不是你想要的方式?
-
嗯,这能解决这个问题吗?如果确实如此,那么我肯定会那样做,但如果不是,我真的看不到它的用途。我唯一需要弄清楚的是如何让 for 循环接收所有客人并删除它们。听起来很简单,但对于我的生活来说,我无法弄清楚为什么。 @bxod
-
deleteUserGuests是您唯一遇到问题的函数吗? -
是的,实际上是唯一的问题,这就是为什么它让我如此沮丧,其他一切都删除得很好。我搜索了带有调度组的嵌套循环,遇到this question,试图实现答案,仍然没有运气。 @bxod
标签: swift google-cloud-firestore nested-loops grand-central-dispatch dispatchgroup