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 分派回主队列。