DispatchQueue.main.async блокирует основной поток - PullRequest
0 голосов
/ 03 ноября 2018

Я пытался создать фотогалерею в Swift 3.0 и хочу асинхронно загружать изображения, хранящиеся в каталоге документов, в представление коллекции. Я попытался DispatchQueue.main.async, но он блокирует основной поток и на несколько секунд останавливает приложение:

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let identifier = "ImageCell"
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: identifier, for: indexPath) as! ImageCell
    let url = self.imageURL[indexPath.row]
    cell.lazyLoadImage(from: url)
    return cell
}

И класс ImageCell:

class ImageCell: UICollectionViewCell {
    @IBOutlet weak var imageView: UIImageView!

    func lazyLoadImage(from url: URL) {
        DispatchQueue.main.async {
            if let image = UIImage(contentsOfFile: url.path) {
                self.imageView.image = image
            }
        }
    }
}

Я ценю вашу помощь. Спасибо.

Ответы [ 2 ]

0 голосов
/ 03 ноября 2018

Вы делаете это неправильно. Короче, могу сказать, что это не «ленивая загрузка». То, что вы делаете, блокирует потоки, чтобы загрузить контент из URL и загрузить его в UIImageView. Поток не будет выпущен до тех пор, пока не произойдет загрузка, и вы не будете использовать его в «повторно используемых ячейках», и это очевидно, что ваше приложение зависнет!

Решение

Существует много самых популярных библиотек, таких как AlamofireImage , SDWebImage , Kingfisher . Из которого я беру "SDWebImage", и вы можете вызвать загрузку изображения async способом с помощью следующего кода:

imageView.sd_setImage(with: url , placeholderImage: nil)

Также, пожалуйста, обратитесь к этому вопросу SO ( как реализовать отложенную загрузку изображений в табличном представлении, используя swift ) для более подробной информации.

0 голосов
/ 03 ноября 2018

Сначала переключитесь на фоновый поток и загрузите на него изображение, а затем снова переключитесь на основной поток и отобразите изображение.

func lazyLoadImage(from url: URL) {
     DispatchQueue.global(qos: .userInteractive).async {
         if let image = UIImage(contentsOfFile: url.path) {
             DispatchQueue.main.async {
                 self.imageView.image = image
             }
         }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...