Сумасшедшие проблемы с памятью при использовании SDWebImage в CollectionView (внутри tableviewCell)

Я не могу понять, почему память моего приложения РАСПРОСТРАНЯЕТСЯ, как только я начинаю прокручивать представление коллекции с представлениями изображений, заполненными SDWebImage. Если они еще не загружены, то какое-то время все в порядке. Но как только каждое изображение загружено, если я даже ПРИКАСАТЬСЯ к прокрутке, пользовательский интерфейс приложения перестает отвечать на запросы, а объем памяти становится настолько большим (более 1 ГБ), что не только происходит сбой приложения, но и вся ОС падает и перезагружается.

У меня есть таблица с несколькими ячейками, одна из которых имеет коллекцию, которую я могу прокручивать. У меня есть объект данных, который я использую для заполнения всех меток и изображений в collectionViewCell. CellForItem был очень сложным (множество операторов if и switch), поэтому я попытался перенести часть кода оттуда и переместить его в метод didSet свойства, которое я установил в collectionViewCell для хранения объекта данных. Затем я просто установил объект данных в свойство в itemForRow (в фоновом потоке), которое вызвало метод didSet отдельной коллекцииViewCell для заполнения меток и установки изображения с помощью метода sd_set_image. Вот соответствующий код в tableViewCell:

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
print(indexPath.row)
if itemStyle == .Grid {

  let cell = collectionView.dequeueReusableCell(withReuseIdentifier: self.resourceCellIdentifier, for: indexPath) as! ResourceCollectionViewCell
  cell.delegate = self
  cell.tag = indexPath.row

  if self.filter == Filter.Collections ||  self.resourceArray?[indexPath.row].actionContent == nil {
    let resource: ActionContentTemplate?
    if self.filter == Filter.Collections {
      resource = self.collectionResourceArray?[indexPath.row].actionContentTemplate
    } else {
      resource = self.resourceArray?[indexPath.row].actionContentTemplate
    }

    DispatchQueue.global(qos: .userInitiated).async {

      cell.dataObject = resource
    }
    return cell

  } else {.....

А это метод didSet в самой CollectionViewCell:

var dataObject: ActionContentTemplate? {
didSet {
  var cellRow: Int = 0

  if self.actionContentTemplate != nil {
    ....

    DispatchQueue.main.async {
      cellRow = self.tag

       .....

      switch self.actionContentTemplate?.contentTypeID?.uintValue {
      case ContentTypeVideo.rawValue,
           ContentTypeVideoRecording.rawValue,
           ContentTypeScreenRecording.rawValue:
        .......
      case ContentTypeAttachment.rawValue:


        let fileType = (self.actionContentTemplate?.contentFileName as NSString?)?.pathExtension.lowercased()
        var placeholderImage: UIImage

        if fileType == "pdf" {
          placeholderImage = UIImage(named: "pdf")!
        } else if fileType == "doc" {
          placeholderImage = UIImage(named: "doc")!
        } else if fileType == "docx" {
          placeholderImage = UIImage(named: "doc")!
        } else if fileType == "xls" {
          placeholderImage = UIImage(named: "xls")!
        } else if fileType == "xlsx" {
          placeholderImage = UIImage(named: "xls")!
        } else if fileType == "ppt" {
          placeholderImage = UIImage(named: "ppt")!
        } else if fileType == "pptx" {
          placeholderImage = UIImage(named: "ppt")!
        } else {
          placeholderImage = UIImage(named: "plain")!
        }

        if let urlString = self.actionContentTemplate?.thumbnailURL {
          let imageURL = URL(string: urlString)

          SDWebImageManager.shared().loadImage(with: imageURL, options: [.continueInBackground, .scaleDownLargeImages], progress: nil) { (image, data, err, cacheType, finished, url) in
              DispatchQueue.main.async {
                if cellRow == self.tag {

                self.activityIndicator?.stopAnimating()
                self.imageView.image = image
                UIAnimation.fadeTransitionImageView(self.imageView)
              }
            }
          }
                      }

        } else {
          DispatchQueue.main.async {

            self.activityIndicator?.stopAnimating()
            self.imageView.image = placeholderImage
          }
        }
        break
.....

На самом деле я переключился на метод loadImage, так как метод sd_setimage тоже не работал.

 SDWebImageManager.shared().loadImage(with: imageURL, options: [.continueInBackground, .scaleDownLargeImages], progress: nil) { (image, data, err, cacheType, finished, url) in
                  DispatchQueue.main.async {
                    if cellRow == self.tag {
//IF I COMMENT OUT THESE TWO LINES BELOW THE ISSUES STOP (I think it is only the self.imageView.image = image line that is causing issues)
         //           self.activityIndicator?.stopAnimating()
         //           self.imageView.image = image
                    UIAnimation.fadeTransitionImageView(self.imageView)
                  }
                }
              }

Может ли кто-нибудь объяснить мне, почему это происходит и что я могу сделать, чтобы это исправить?

РЕДАКТИРОВАТЬ - забыл добавить эти настройки в делегат приложения на вопрос:

//Settings for image caching
  [[SDWebImageDownloader sharedDownloader] setShouldDecompressImages:NO];

  [[[SDImageCache sharedImageCache] config] setShouldDecompressImages:NO];
  [[[SDImageCache sharedImageCache] config] setShouldCacheImagesInMemory:NO];
  [[[SDImageCache sharedImageCache] config] setMaxCacheSize:1024 * 1024 * 100];
  [[[SDImageCache sharedImageCache] config] setMaxCacheAge:3600 * 24 * 7];
  [[SDImageCache sharedImageCache] setMaxMemoryCost:1024 * 1024 * 15];

person Tom A    schedule 21.02.2019    source источник


Ответы (1)


Оказалось, что миниатюры были довольно большими, и по этой ссылке (iOS Swift : Как правильно уменьшить изображение?), чтобы изменить размер изображения до размера imageView, полностью устранена проблема с памятью. Тем не менее, прокрутка немного прерывистая после загрузки изображений ... Я думал, что перемещение большей части кода вычислений в фоновый поток и из cellForItem поможет в этом, но я, очевидно, что-то упускаю. Если кто-нибудь может указать мне правильное направление, это будет оценено, поскольку я всегда пытаюсь узнать больше как разработчик.

person Tom A    schedule 21.02.2019