Swift iOS - 带有 URLSession 的 DispatchGroup 正在锁定它不在的应用程序的其他部分
Swift iOS -DispatchGroup with URLSession is locking other parts of app that it is not located in
我有一个最多包含 6 张图片的数组。我使用循环遍历所有图像,将它们转换为元数据,将元数据发送到存储,然后在完成后将 url 字符串发送到 Firebase 数据库。
我正在使用 DispatchGroup 来控制循环,因为 Url 已更改为数据,因此我可以将数据发送到 Firebase 存储。
如果此循环发生在 tabOne 中,如果我来回切换到 tabTwo 或 tabThree,当循环结束并出现警报时,tabTwo 被暂时锁定或 tabThree 被暂时锁定大约 2-3 秒。我不知道哪里出错了?
我不确定这是否有所不同,但我使用的是自定义警报而不是 UIAlertController。它只是一些 UIViews 和一个按钮,没什么特别的,所以我没有包含代码。
var urls = [URL]()
picUUID = UUID().uuidString
dict = [String:Any]()
let myGroup = DispatchGroup()
var count = 0
for url in urls{
myGroup.enter() // enter group here
URLSession.shared.dataTask(with: url!, completionHandler: {
(data, response, error) in
guard let data = data, let _ = error else { return }
DispatchQueue.main.async{
self.sendDataToStorage("\(self.picUUID)_\(self.count).jpg", picData: data)
self.count += 1
}
}).resume()
// send dictionary data to firebase when loop is done
myGroup.notify(queue: .main) {
self.sendDataToFirebaseDatabase()
self.count = 0
}
}
func sendDataToStorage(_ picId: String, picData: Data?){
dict.updateValue(picId, forKey:"picId_\(count)")
let picRef = storageRoot.child("pics")
picRef.putData(picData!, metadata: nil, completion: { (metadata, error) in
if let picUrl = metadata?.downloadURL()?.absoluteString{
self.dict.updateValue(picUrl, forKey:"picUrl_\(count)")
self.myGroup.leave() // leave group here
}else{
self.myGroup.leave() // leave group if picUrl is nil
}
}
}
func sendDataToFirebaseDatabase(){
let ref = dbRoot.child("myRef")
ref.updateChildValues(dict, withCompletionBlock: { (error, ref) in
displaySuccessAlert()
}
}
我不太了解 Firebase,但您正在将 sendDataToFirebaseDatabase
方法分派到主队列,这可能解释了为什么您的 UI 变得没有响应。
将 sendDataToFirebaseDatabase
分派到后台队列,仅将 displaySuccessAlert
分派回主队列。
我有一个最多包含 6 张图片的数组。我使用循环遍历所有图像,将它们转换为元数据,将元数据发送到存储,然后在完成后将 url 字符串发送到 Firebase 数据库。
我正在使用 DispatchGroup 来控制循环,因为 Url 已更改为数据,因此我可以将数据发送到 Firebase 存储。
如果此循环发生在 tabOne 中,如果我来回切换到 tabTwo 或 tabThree,当循环结束并出现警报时,tabTwo 被暂时锁定或 tabThree 被暂时锁定大约 2-3 秒。我不知道哪里出错了?
我不确定这是否有所不同,但我使用的是自定义警报而不是 UIAlertController。它只是一些 UIViews 和一个按钮,没什么特别的,所以我没有包含代码。
var urls = [URL]()
picUUID = UUID().uuidString
dict = [String:Any]()
let myGroup = DispatchGroup()
var count = 0
for url in urls{
myGroup.enter() // enter group here
URLSession.shared.dataTask(with: url!, completionHandler: {
(data, response, error) in
guard let data = data, let _ = error else { return }
DispatchQueue.main.async{
self.sendDataToStorage("\(self.picUUID)_\(self.count).jpg", picData: data)
self.count += 1
}
}).resume()
// send dictionary data to firebase when loop is done
myGroup.notify(queue: .main) {
self.sendDataToFirebaseDatabase()
self.count = 0
}
}
func sendDataToStorage(_ picId: String, picData: Data?){
dict.updateValue(picId, forKey:"picId_\(count)")
let picRef = storageRoot.child("pics")
picRef.putData(picData!, metadata: nil, completion: { (metadata, error) in
if let picUrl = metadata?.downloadURL()?.absoluteString{
self.dict.updateValue(picUrl, forKey:"picUrl_\(count)")
self.myGroup.leave() // leave group here
}else{
self.myGroup.leave() // leave group if picUrl is nil
}
}
}
func sendDataToFirebaseDatabase(){
let ref = dbRoot.child("myRef")
ref.updateChildValues(dict, withCompletionBlock: { (error, ref) in
displaySuccessAlert()
}
}
我不太了解 Firebase,但您正在将 sendDataToFirebaseDatabase
方法分派到主队列,这可能解释了为什么您的 UI 变得没有响应。
将 sendDataToFirebaseDatabase
分派到后台队列,仅将 displaySuccessAlert
分派回主队列。