Swift Grand Central Диспетчерские очереди и UIImages - PullRequest
0 голосов
/ 09 мая 2018

Я знаю, что этот тип вопроса задавался 1e7 раз, но я столкнулся с конкретной проблемой, которая, как мне кажется, не была рассмотрена / явно очевидна, но я слишком новичок, чтобы решить ее самостоятельно.

У меня есть следующий фрагмент кода в моем методе cellForRowAt в 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!)
        }
    }
}

Выполняется нормально, загружает изображения и присваивает их UIImageView каждого tableViewCell.

При прокрутке таблицы существует конечная задержка, так как изображения загружаются «на лету», так сказать.

Я хочу предварительно загрузить все эти изображения и сохранить их в структуре данных, чтобы они реже выбирались из 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, а хранить их для дальнейшего использования?

1 Ответ

0 голосов
/ 09 мая 2018

Проблема в том, что вы создаете 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...) также не работает: вы не должны ссылаться на ячейку внутри закрытия отправки:

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

Вместо этого, обратитесь к IndexPath, найдите ячейку внутри clousure и продолжайте с этой ячейкой. Но, как вы уже упоминали, в стеке потока много записей о данной проблеме.

...