简体   繁体   English

带有URLSession的Swift iOS -DispatchGroup锁定了未位于其中的应用程序的其他部分

[英]Swift iOS -DispatchGroup with URLSession is locking other parts of app that it is not located in

I have an array of up to 6 images. 我有最多6张图片的阵列。 I use a loop to loop through all of the images, turn them into metadata, send the metadata to Storage and then when done I send the url strings to Firebase Database. 我使用循环遍历所有图像,将它们转换为元数据,将元数据发送到存储,然后在完成后将url字符串发送到Firebase数据库。

I'm using DispatchGroup to control the loop as the Url is changed to Data so I can send the data to Firebase Storage. 当Url更改为Data时,我正在使用DispatchGroup来控制循环,因此可以将数据发送到Firebase Storage。

If this loop is happening in tabOne, if i go back and forth to tabTwo or tabThree, when the loop finishes and the alert appears, tabTwo is temporarily locked or tabThree gets temporarily locked for around 2-3 seconds. 如果在tabOne中发生此循环,如果我来回切换至tabTwo或tabThree,则在循环结束并显示警报时,tabTwo被临时锁定,或者tabThree被临时锁定约2-3秒。 I cannot figure out where I'm going wrong? 我无法弄清楚哪里出了问题?

I'm not sure if it makes a difference but I'm using a custom alert instead of the UIAlertController. 我不确定是否会有所不同,但我使用的是自定义提醒,而不是UIAlertController。 It's just some UIViews and a button, it's nothing special so I didn't include the code. 它只是一些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()
    }
}

I don't know much about Firebase, but you are dispatching your sendDataToFirebaseDatabase method to main queue which probably explains why your UI becomes unresponsive. 我对Firebase不太了解,但是您正在将sendDataToFirebaseDatabase方法调度到主队列,这可能解释了UI变得无响应的原因。

Dispatch sendDataToFirebaseDatabase to a background queue and only dispatch your displaySuccessAlert back to main queue. sendDataToFirebaseDatabase到后台队列,仅将displaySuccessAlert分配回主队列。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM