我正在阅读这个关于应用程序冻结和信号量的问题,我试图在我的代码中实现答案,但是尽管在主线程上调用 UI 工作,它仍然冻结了我的应用程序。我的目标是在调用所有条目后停止应用程序冻结并让 UI 正常工作。
这是迄今为止我在删除方法中的警报操作:
let deleteAction = UIAlertAction(title: "Delete", style: .destructive) { (deletion) in
let semaphore = DispatchSemaphore(value: 0)
self.deleteButton.isHidden = true
self.loadingToDelete.alpha = 1
self.loadingToDelete.startAnimating()
DispatchQueue.global(qos: .userInitiated).async {
self.db.collection("student_users/\(user.uid)/events_bought").getDocuments { (querySnapshot, error) in
guard error == nil else {
print("The docs couldn't be retrieved for deletion.")
return
}
guard querySnapshot?.isEmpty == false else {
print("The user being deleted has no events purchased.")
return
}
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
}
for doc in querySnap!.documents {
let guest = doc.documentID
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!")
semaphore.signal()
}
semaphore.wait()
}
}
}
}
self.db.collection("student_users/\(user.uid)/events_bought").getDocuments { (querySnapshot, error) in
guard error == nil else {
print("There was an error retrieving docs for user deletion.")
return
}
guard querySnapshot?.isEmpty == false else {
return
}
for document in querySnapshot!.documents {
let docID = document.documentID
self.db.document("student_users/\(user.uid)/events_bought/\(docID)").delete { (err) in
guard err == nil else {
print("There was an error deleting the the purchased events for the user being deleted.")
return
}
print("Purchases have been deleted for deleted user!")
semaphore.signal()
}
semaphore.wait()
}
}
self.db.document("student_users/\(user.uid)").delete(completion: { (error) in
guard error == nil else {
print("There was an error deleting the user document.")
return
}
print("User doc deleted!")
semaphore.signal()
})
semaphore.wait()
user.delete(completion: { (error) in
guard error == nil else {
print("There was an error deleting user from the system.")
return
}
print("User Deleted.")
semaphore.signal()
})
semaphore.wait()
DispatchQueue.main.async {
self.loadingToDelete.stopAnimating()
self.performSegue(withIdentifier: Constants.Segues.studentUserDeletedAccount, sender: self)
}
}
}
所以这实际上会干净地删除所有内容,Firestore 数据库中没有任何残留数据,这就是我一直想要发生的事情,唯一的问题是应用程序冻结。我认为我上面链接的问题的答案适用于我的情况,但事实并非如此。
还要提一下,我曾建议使用 Cloud Functions 解决此问题,但我的应用程序有两种类型的用户,在删除过程中具有不同的逻辑和语法,因此我不能只auth().onDelete()
在 Cloud Functions 中使用简单的并清理残留物。即使我可以,这将是我在这里面临的相同问题,但只是在服务器端,试图正确排序任务,在我看来这是重复的,而不是目前最明智的做法。
有什么其他建议可以解决这个问题吗?提前致谢。
编辑由于信号量不是要走的路,我求助于这个:
let deleteAction = UIAlertAction(title: "Delete", style: .destructive) { (deletion) in
self.deleteButton.isHidden = true
self.loadingToDelete.alpha = 1
self.loadingToDelete.startAnimating()
self.db.collection("student_users/\(user.uid)/events_bought").getDocuments { (querySnapshot, error) in
guard error == nil else {
print("The docs couldn't be retrieved for deletion.")
return
}
guard querySnapshot?.isEmpty == false else {
print("The user being deleted has no events purchased.")
return
}
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()
}
}
}
}
}
self.db.collection("student_users/\(user.uid)/events_bought").getDocuments { (querySnapshot, error) in
guard error == nil else {
print("There was an error retrieving docs for user deletion.")
return
}
guard querySnapshot?.isEmpty == false else {
return
}
let group = DispatchGroup()
for document in querySnapshot!.documents {
let docID = document.documentID
group.enter()
self.db.document("student_users/\(user.uid)/events_bought/\(docID)").delete { (err) in
guard err == nil else {
print("There was an error deleting the the purchased events for the user being deleted.")
return
}
print("Purchases have been deleted for deleted user!")
group.leave()
}
}
}
self.db.collection("student_users").whereField("userID", isEqualTo: user.uid).getDocuments { (querySnapshot, error) in
guard error == nil else {
print("There was an error deleting the user document.")
return
}
guard querySnapshot?.isEmpty == false else {
return
}
let group = DispatchGroup()
for document in querySnapshot!.documents {
let docID = document.documentID
group.enter()
self.db.document("student_users/\(docID)").delete { (err) in
guard err == nil else {
return
}
print("User doc deleted!")
group.leave()
}
}
}
let group = DispatchGroup()
group.enter()
user.delete(completion: { (error) in
guard error == nil else {
print("There was an error deleting user from the system.")
return
}
print("User Deleted.")
group.leave()
})
group.notify(queue: .main) {
self.loadingToDelete.stopAnimating()
self.performSegue(withIdentifier: Constants.Segues.studentUserDeletedAccount, sender: self)
}
}
这仍然会留下残留数据,并且不会按顺序执行任务。还有其他建议吗?