我知道这类问题已经被问过17次了,但我遇到了一个我认为没有涉及到的具体问题/这是显而易见的,但我太新手了,无法自己解决。
在acellForRowAt中的TableViewController方法中有以下代码片段:

let currentDictionary = parser.parsedData[indexPath.row] as Dictionary<String,String>

let urlString = currentDictionary["media:content"]

if urlString != nil {
    let url = NSURL(string: urlString!)
    DispatchQueue.global().async {
        let data = try? Data(contentsOf: url! as URL) //make sure your image in this url does exist, otherwise unwrap in a if let check / try-catch
        DispatchQueue.main.async {
            cell.thumbnailImageView.image = UIImage(data: data!)
        }
    }
}

它执行良好,下载图像并将它们分配给每个UIImageViewtableViewCell
可以说,当图像“动态”下载时,滚动表格会有有限的延迟。
我想做的是预先下载所有这些图片,并将它们保存在一个数据结构中,这样它们就不会频繁地从URL获取。
我尝试了以下实现:
var thumbnail = UIImage()

for item in parser.parsedData {
    let currentDictionary = item as Dictionary<String,String>
    let title = currentDictionary["title"]
    let link = currentDictionary["link"]
    let urlString = currentDictionary["media:content"]
    let url = NSURL(string: urlString!)


    if urlString != nil {
        let url = NSURL(string: urlString!)
        DispatchQueue.global().async {
            let data = try? Data(contentsOf: url! as URL)
            DispatchQueue.main.sync {
                thumbnail = UIImage(data: data!)!
            }
        }
    }

    var newsArticle: News!
    newsArticle = News(title: title!, link: link!, thumbnail: thumbnail)

    news.append(newsArticle)

新闻是我的数据结构。这段代码也执行得很好,但是根据控制台的输出,每个缩略图都是一个0x0大小的图像,大小{0,0}方向0比例1.000000。
是否有人知道如何下载这些图像,但不立即将其分配给UIImageView,而是将其存储以备以后使用?

最佳答案

问题是,您甚至在全局调度队列开始处理您的newsArticle之前就创建了url。因此,thumbnail仍然是第一行中创建的空UIImage()
您必须在内部分派闭包中创建缩略图,例如:

for item in parser.parsedData {
    guard let currentDictionary = item as? Dictionary<String,String>    else { continue /* or some error handling */ }
    guard let title = currentDictionary["title"]                        else { continue /* or some error handling */ }
    guard let link = currentDictionary["link"]                          else { continue /* or some error handling */ }
    guard let urlString = currentDictionary["media:content"]            else { continue /* or some error handling */ }
    guard let url = URL(string: urlString)                              else { continue /* or some error handling */ }

    DispatchQueue.global().async {
        if let data = try? Data(contentsOf: url) {
            DispatchQueue.main.sync {
                if let thumbnail = UIImage(data: data) {
                    let newsArticle = News(title: title, link: link, thumbnail: thumbnail)

                    news.append(newsArticle)
                }
            }

        }
    }
}

顺便说一下,您的第一个代码(cellForRow...)也被破坏了:您不能引用dispatch闭包中的单元格:
DispatchQueue.main.async {
    // Never do this
    cell.thumbnailImageView.image = UIImage(data: data!)
}

相反,引用IndexPath,检索clousure中的单元格,然后继续使用该单元格。但是正如您已经提到的,stackoverflow上有很多关于这个问题的条目。

关于ios - Swift Grand Central调度队列和UIImages,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/50249992/

10-11 21:38