Решение в вашем комментарии get image with asynchronous completion handler
.Без семафора все загрузки изображений начнутся одновременно и начнут гонку за завершением, поэтому самое быстрое загружаемое изображение будет сначала добавлено в массив.
Таким образом, после начала загрузки вы сразу же ждете своего семафора.,Это будет блокироваться до тех пор, пока не будет сообщено в закрытии обратного вызова из метода getData.Только тогда цикл может перейти к следующему документу и загрузить его.Таким образом, вы загружаете один файл за другим и блокируете текущий поток во время загрузки.
Использование последовательной очереди здесь не вариант, так как это приведет только к загрузке до start серийно, но вы не можете повлиять на порядок, в котором они заканчиваются.
Это довольно неэффективно, хотя.Ваш сетевой уровень, вероятно, может работать быстрее, если вы дадите ему несколько запросов одновременно (подумайте о параллельных загрузках и конвейерной передаче HTTP).Кроме того, вы «тратите» поток, который тем временем может выполнять какую-то другую работу.Если в это же время нужно проделать больше работы, GCD создаст другой поток, который тратит впустую память и другие ресурсы.
Лучше было бы пропустить семафор, пусть загрузки будут выполняться параллельно и напрямую сохранять изображениена правильный индекс в вашем массиве.Это, конечно, означает, что вам нужно заранее подготовить массив соответствующего размера и подумать о заполнителе для отсутствующих или неудачных изображений.Факультативные функции хорошо бы сработали:
var images: [UIImage?] = Array(repeating: nil, count: snapshot.documents.count)
for (index, doc) in snapshot.documents.enumerated() {
// create data object for array
dispatchGroup.enter()
// get image with asynchronous completion handler
Storage.storage().reference(forURL: imageId).getData(maxSize: 1048576) { data, error in
defer {
dispatchGroup.leave()
}
if let imageData = data,
error == nil {
// add image to data object
images[index] = image
}
}
}