如何从 URL 数组下载图像并将其一张一张附加到数组 Swift
How to download the image from URL array and append it to an array one by one Swift
我尝试从 URL 数组下载图像并将图像附加到我的 collection 视图的图像数组。但它不会将其一张一张地下载并附加到图像数组中。所以我尝试使用调度组,但没有用。正确的添加调度组的方法是什么?
func downloadPhoto(){
progressImgArray.removeAll() // this is the image array
for i in 0..<progressArray.count{
let urls = URL(string: progressArray[i].userProgressImage) // this is the URL array
let group = DispatchGroup()
print(urls ?? "nil image")
print("-------GROUP ENTER-------")
group.enter()
URLSession.shared.dataTask(with: urls!, completionHandler: { data, response, error in
print(response?.suggestedFilename ?? urls?.lastPathComponent ?? "nil image")
if let imgData = data {
if UIImage(data: imgData) != nil {
DispatchQueue.main.async() {
self.progressImgArray.append(UIImage(data: data!)!)
}
}
}
group.leave()
}).resume()
group.notify(queue: .main) {
self.collectionView.reloadData()
}
}
}
打印:顺序错误
http://sweat.asia/app/users_progresses/users_progresses_111_761319316286fcb38a0b.png
-------GROUP ENTER-------
http://sweat.asia/app/users_progresses/users_progresses_111_263983427965d44f5021.png
-------GROUP ENTER-------
http://sweat.asia/app/users_progresses/users_progresses_111_3361893721fa8f84015a.png
-------GROUP ENTER-------
users_progresses_111_263983427965d44f5021.png
users_progresses_111_761319316286fcb38a0b.png
users_progresses_111_3361893721fa8f84015a.png
怎么做成这样
http://sweat.asia/app/users_progresses/users_progresses_111_761319316286fcb38a0b.png
-------GROUP ENTER-------
users_progresses_111_761319316286fcb38a0b.png
http://sweat.asia/app/users_progresses/users_progresses_111_263983427965d44f5021.png
-------GROUP ENTER-------
users_progresses_111_263983427965d44f5021.png
...
您的问题是 group.notify
将阻塞,直到调度组为空。但是你在任何 "leaves" 被调用之前用三个 "enters" 填充它所以 "notify" 不会发生直到第三个 "leave" 发生。
相反 "notify" 您需要使用 "wait"。要使用 "wait",您需要将整个内容放在一个新的后台线程中。
更新后的代码应该如下所示:
func downloadPhoto(){
DispatchQueue.global().async {
progressImgArray.removeAll() // this is the image array
for i in 0..<progressArray.count {
guard let url = URL(string: progressArray[i].userProgressImage) else {
continue
}
let group = DispatchGroup()
print(url)
print("-------GROUP ENTER-------")
group.enter()
URLSession.shared.dataTask(with: url, completionHandler: { data, response, error in
print(response?.suggestedFilename ?? url.lastPathComponent)
if let imgData = data, let image = UIImage(data: imgData) {
DispatchQueue.main.async() {
self.progressImgArray.append(image)
self.collectionView.reloadData()
}
} else if let error = error {
print(error)
}
group.leave()
}).resume()
group.wait()
}
}
}
我还进行了其他几项改进,包括更好地处理可选值。
rmaddy 回答的小更新:
Get Notified when array is full with downloaded images.
func downloadImageFromUrl()
{
DispatchQueue.global().async
{
self.imageArray.removeAll()
let dispatchGroup = DispatchGroup()
for i in 0..<(self.imageUrlArray?.count)!
{
guard let url = URL(string: (self.imageUrlArray?![i])!)
else{ continue }
dispatchGroup.enter()
Alamofire.request(url).responseData(completionHandler: { response in
guard
let data = response.result.value,
let image = UIImage(data:data)
else {
print("Error in downlaoding images : ",(response.error?.localizedDescription)!)
return
}
DispatchQueue.main.async {
self.imageArray.append(image)
}
dispatchGroup.leave()
})
dispatchGroup.wait()
}
dispatchGroup.notify(queue: DispatchQueue.main,execute: {
print("are we done.... :",self.imageArray.count)
self.yourCollection.reloadData()
})
}
}
I mean for me it is really working like a charm, I've a tableview in which one of the cell of tableview contains Collection View
我尝试从 URL 数组下载图像并将图像附加到我的 collection 视图的图像数组。但它不会将其一张一张地下载并附加到图像数组中。所以我尝试使用调度组,但没有用。正确的添加调度组的方法是什么?
func downloadPhoto(){
progressImgArray.removeAll() // this is the image array
for i in 0..<progressArray.count{
let urls = URL(string: progressArray[i].userProgressImage) // this is the URL array
let group = DispatchGroup()
print(urls ?? "nil image")
print("-------GROUP ENTER-------")
group.enter()
URLSession.shared.dataTask(with: urls!, completionHandler: { data, response, error in
print(response?.suggestedFilename ?? urls?.lastPathComponent ?? "nil image")
if let imgData = data {
if UIImage(data: imgData) != nil {
DispatchQueue.main.async() {
self.progressImgArray.append(UIImage(data: data!)!)
}
}
}
group.leave()
}).resume()
group.notify(queue: .main) {
self.collectionView.reloadData()
}
}
}
打印:顺序错误
http://sweat.asia/app/users_progresses/users_progresses_111_761319316286fcb38a0b.png
-------GROUP ENTER-------
http://sweat.asia/app/users_progresses/users_progresses_111_263983427965d44f5021.png
-------GROUP ENTER-------
http://sweat.asia/app/users_progresses/users_progresses_111_3361893721fa8f84015a.png
-------GROUP ENTER-------
users_progresses_111_263983427965d44f5021.png
users_progresses_111_761319316286fcb38a0b.png
users_progresses_111_3361893721fa8f84015a.png
怎么做成这样
http://sweat.asia/app/users_progresses/users_progresses_111_761319316286fcb38a0b.png
-------GROUP ENTER-------
users_progresses_111_761319316286fcb38a0b.png
http://sweat.asia/app/users_progresses/users_progresses_111_263983427965d44f5021.png
-------GROUP ENTER-------
users_progresses_111_263983427965d44f5021.png
...
您的问题是 group.notify
将阻塞,直到调度组为空。但是你在任何 "leaves" 被调用之前用三个 "enters" 填充它所以 "notify" 不会发生直到第三个 "leave" 发生。
相反 "notify" 您需要使用 "wait"。要使用 "wait",您需要将整个内容放在一个新的后台线程中。
更新后的代码应该如下所示:
func downloadPhoto(){
DispatchQueue.global().async {
progressImgArray.removeAll() // this is the image array
for i in 0..<progressArray.count {
guard let url = URL(string: progressArray[i].userProgressImage) else {
continue
}
let group = DispatchGroup()
print(url)
print("-------GROUP ENTER-------")
group.enter()
URLSession.shared.dataTask(with: url, completionHandler: { data, response, error in
print(response?.suggestedFilename ?? url.lastPathComponent)
if let imgData = data, let image = UIImage(data: imgData) {
DispatchQueue.main.async() {
self.progressImgArray.append(image)
self.collectionView.reloadData()
}
} else if let error = error {
print(error)
}
group.leave()
}).resume()
group.wait()
}
}
}
我还进行了其他几项改进,包括更好地处理可选值。
rmaddy 回答的小更新:
Get Notified when array is full with downloaded images.
func downloadImageFromUrl()
{
DispatchQueue.global().async
{
self.imageArray.removeAll()
let dispatchGroup = DispatchGroup()
for i in 0..<(self.imageUrlArray?.count)!
{
guard let url = URL(string: (self.imageUrlArray?![i])!)
else{ continue }
dispatchGroup.enter()
Alamofire.request(url).responseData(completionHandler: { response in
guard
let data = response.result.value,
let image = UIImage(data:data)
else {
print("Error in downlaoding images : ",(response.error?.localizedDescription)!)
return
}
DispatchQueue.main.async {
self.imageArray.append(image)
}
dispatchGroup.leave()
})
dispatchGroup.wait()
}
dispatchGroup.notify(queue: DispatchQueue.main,execute: {
print("are we done.... :",self.imageArray.count)
self.yourCollection.reloadData()
})
}
}
I mean for me it is really working like a charm, I've a tableview in which one of the cell of tableview contains Collection View