简体   繁体   中英

Swift Grand Central Dispatch Queues and UIImages

I know this type of question has been asked 1e7 times but I have come across a specific issue that I don't think has been covered/is blatantly obvious but I am too novice to fix it on my own.

I have the following code snippet within my cellForRowAt method in a 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!)
        }
    }
}

Which executes fine, downloads the images and assigns them to the UIImageView of each tableViewCell .

There is a finite delay when scrolling the table as the images are downloaded 'on the fly' so to speak.

What I want to do is pre-download all these images and save them in a data structure so they are fetched from URL's less frequently.

I have tried the following implementation:

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)

Where news is my data structure. This code also executes fine, however each thumbnail is a 0x0 sized image, size {0, 0} orientation 0 scale 1.000000, according to the console output.

Does anyone have any ideas how to download these images but not immediately assign them to a UIImageView , rather store them for later use?

The problem is that you create your newsArticle before the global dispatch queue even started to process your url . Therefore, thumbnail is still the empty UIImage() created in the very first line.

You'll have to create the thumbnail inside the inner dispatch closure, like:

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)
                }
            }

        }
    }
}

By the way, your very first code ( cellForRow... ) is also broken: You must not reference the cell inside the dispatch closure:

DispatchQueue.main.async {
    // Never do this
    cell.thumbnailImageView.image = UIImage(data: data!)
} 

Instead, reference the IndexPath , retrieve the cell inside the clousure, and go on with that cell. But as you already mentioned, there are many many entries on stackoverflow regarding this issue.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM