Я перебираю несколько Url
с, преобразую их в Data
, затем отправляю данные в Firebase Storage
, а затем, когда все сделано, отправляю собранную информацию в Firebase Database
Я использую DispatchGroup() * .enter()
, чтобы запустить цикл, и как только я отправляю данные в хранилище и получаю строку URL-адреса значения absoluteString
Я использую .leave()
, чтобы начать следующую итерацию.
Я понял, чтово время цикла есть несколько точек, где могут возникать ошибки:
- один раз внутри
UrlSession
- один раз внутри функции Storage
.putData
- один раз внутри Storage
.downloadURL(completion:...
обработчик завершения - и снова, если конечный параметр downloadURL
?.absoluteString
равен nil
Если я получаю ошибку в любой из этих точек, я показываю функцию предупреждения showAlert(
)который показывает предупреждение и отменяет UrlSession с session.invalidateAndCancel()
.Я отменяю все, потому что я хочу, чтобы пользователь начал все заново.
Поскольку DispatchGroup () остается висеть на .enter()
, как мне отменить DispatchGroup (), чтобы остановить цикл?
var urls = [URL]()
var picUUID = UUID().uuidString
var dict = [String:Any]()
let session = URLSession.shared
let myGroup = DispatchGroup()
var count = 0
for url in urls{
myGroup.enter()
session.dataTask(with: url!, completionHandler: {
(data, response, error) in
if error != nil {
self.showAlert() // 1st point of error
return
}
DispatchQueue.main.async{
self.sendDataToStorage("\(self.picUUID)_\(self.count).jpg", picData: data)
self.count += 1
}
}).resume()
myGroup.notify(queue: .global(qos: .background) {
self.sendDataFromDictToFirebaseDatabase()
self.count = 0
self.session.invalidateAndCancel()
}
}
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 error != nil{
self.showAlert() // 2nd point of error
return
}
picRef?.downloadURL(completion: { (url, error) in
if error != nil{
self.showAlert() // 3rd point of error
return
}
if let picUrl = url?.absoluteString{
self.dict.updateValue(picUrl, forKey:"picUrl_\(count)")
self.myGroup.leave() //only leave the group if a Url string was obtained
}else{
self.showAlert() // 4th point of error
}
})
})
}
func showAlert(){
// the DispatchGroup() should get cancelled here
session.invalidateAndCancel()
count = 0
UIAlertController...
}
func sendDataFromDictToFirebaseDatabase(){
}