问题描述
我正在尝试从网址数组中检索图像。
我有这个功能,但不能正常工作,所以我尝试使用URLSession,但不知道该怎么做>>
func downloadImages(imageUrls: [String],completion: @escaping (_ images: [UIImage?]) -> Void) {
var imageArray: [UIImage] = []
var downloadCounter = 0
for link in imageUrls {
let url = NSURL(string: link)
let downloadQueue = dispatchQueue(label: "imageDowmloadQueue")
downloadQueue.sync {
downloadCounter += 1
let data = NSData(contentsOf: url! as URL)
if data != nil {
//image data ready and need to be converted to UIImage
imageArray.append(UIImage(data: data! as Data)!)
if downloadCounter == imageArray.count {
dispatchQueue.main.async {
completion(imageArray)
}
}
} else {
print("Couldnt download image")
completion(imageArray)
}
}
}
}
我正在使用的功能:
public func imagesFromURL(urlString: [String],completion: @escaping (_ images: [UIImage?]) -> Void) {
var imageArray: [UIImage] = []
var downloadCounter = 0
let downloadQueue = dispatchQueue(label: "imageDowmloadQueue")
for link in urlString {
downloadQueue.sync {
downloadCounter += 1
let dataTask = URLSession.shared.dataTask(with: NSURL(string: link)! as URL,completionHandler: { (data,response,error ) in
if error != nil {
print(error ?? "No Error")
return
}
if data != nil {
imageArray.append(UIImage(data: data! as Data)!)
if downloadCounter == imageArray.count {
completion(imageArray)
}
} else {
print("Couldnt download image")
completion(imageArray)
}
} dataTask.resume()
}
}
}
我想调用集合单元中的函数,并仅从每个图稿阵列中获得第一张图像的显示。
//download the first image only to display it:
if artwork.ImgLink != nil && artwork.ImgLink.count > 0 {
downloadImages(imageUrls: [artwork.ImgLink.first!]) { (images) in
self.artworkImage.image = images.first as? UIImage
}
}
解决方法
- 如果打算仅使用URL数组中的第一个可用
UIImage
,则不要设计一个试图下载所有URL的函数。相反,尝试从第一个URL下载,如果下载成功,则返回下载的UIImage
,如果失败,则返回第二个URL,重复直到获得UIImage
。 - 在本地函数中创建
DispatchQueue
对我来说似乎很危险。一种更常见的做法是在其他地方维护队列,并将其作为参数传递给函数,或者,如果没有特殊原因,则使用DispatchQueue.global(qos:)
重用预定义的全局队列之一。 - 请注意
sync
。sync
阻塞调用线程,直到您的阻塞在队列中完成为止。通常,您使用async
。 - 使用
Int
计数器来控制何时完成多个异步任务(何时调用完成块),但是可以通过使用DispatchGroup
来改进,firstImage(inURLs:completion:)
可以简单明了地处理多个异步任务方式。
这是两个功能。两者都可以。 UIImage
仅返回成功下载的第一个images(forURLs:completion:)
。 func firstImage(inURLs urls: [String],completion: @escaping (UIImage?) -> Void) {
DispatchQueue.global().async {
for urlString in urls {
if let url = URL(string: urlString) {
if let data = try? Data(contentsOf: url),let image = UIImage(data: data) {
DispatchQueue.main.async {
completion(image)
}
return
}
}
}
DispatchQueue.main.async {
completion(nil)
}
}
}
// Use it.
firstImage(inURLs: artwork.ImgLink) { image in
self.artworkImage.image = image
}
尝试下载并全部返回。
func images(forURLs urls: [String],completion: @escaping ([UIImage?]) -> Void) {
let group = DispatchGroup()
var images: [UIImage?] = .init(repeating: nil,count: urls.count)
for (index,urlString) in urls.enumerated() {
group.enter()
DispatchQueue.global().async {
var image: UIImage?
if let url = URL(string: urlString) {
if let data = try? Data(contentsOf: url) {
image = UIImage(data: data)
}
}
images[index] = image
group.leave()
}
}
group.notify(queue: .main) {
completion(images)
}
}
// Use it.
images(forURLs: artwork.ImgLink) { images in
self.artworkImage.image = images.first(where: { $0 != nil }) ?? nil
}
https://smap.cas.mcmaster.ca/wp-admin/post.php?post=1035&action=edit