Сумасшедшие проблемы с памятью при использовании SDWebImage в CollectionView (внутри tableviewCell) - PullRequest
0 голосов
/ 21 февраля 2019

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

У меня есть таблица с несколькими ячейками, одна из которых имеет коллекцию, которую я могу прокручивать.У меня есть объект данных, который я использую, чтобы заполнить все метки и изображения в collectionViewCell.CellForItem был очень сложным (много операторов if и операторов switch), поэтому я попытался переместить часть кода оттуда и переместить его в метод didSet свойства, которое я установил в collectionViewCell для хранения объекта данных.Затем я просто установил объект данных для свойства в itemForRow (в фоновом потоке), которое вызвало метод didSet отдельного collectionViewCell для заполнения меток и установки изображения с помощью метода 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];

1 Ответ

0 голосов
/ 22 февраля 2019

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

...