dismissViewController не освобождает память от использования кэшированных изображений. Swift

#ios #swift #memory-management #uiimageview

#iOS #swift #управление памятью #uiimageview

Вопрос:

Заголовок моего вопроса может оставить желать лучшего, но вот основная проблема:

Я представляю a UIViewController , к которому UIScrollView добавлен a . Внутри прокрутки я размещаю множество предварительно загруженных изображений, используя UIImageView «s», где сами изображения кэшируются из моих ресурсов изображений. Изображения довольно большие, так как они действительно хорошего качества. Когда UIViewController представлено, для размещения изображений выделяется много памяти, но когда VC отклоняется dismissViewControllerAnimated , кажется, что вся память из VC освобождается, кроме памяти из изображений (что на самом деле составляет большую часть используемой памяти).

Я попытался сохранить изображения в массиве необязательных изображений, например: [UIImageView?] , а затем прямо перед вызовом для отклонения VC, вызывая removeFromSuperview каждый из них, затем устанавливая значение nil .

Проблема в том, что независимо от того, что я делаю, память никогда не освобождается. Как я могу гарантировать, что память, используемая для этих изображений, правильно освобождается при UIViewController увольнении?

Вот как UIImageView они расположены:

     for i in 0 ..< preLoadedImageNames.count {

        let contentWidth:CGFloat = min(self.view.bounds.width, self.view.bounds.height)/3
        let contentHeight:CGFloat = height

        let content:UIView = UIView()
        scroll.addSubview(content)
        content.translatesAutoresizingMaskIntoConstraints = false
        let contentHeightConstraint:NSLayoutConstraint = NSLayoutConstraint(item: content, attribute: NSLayoutAttribute.Height, relatedBy: NSLayoutRelation.Equal, toItem: nil, attribute: NSLayoutAttribute.NotAnAttribute, multiplier: 1, constant: contentHeight)
        let contentWidthConstraint:NSLayoutConstraint = NSLayoutConstraint(item: content, attribute: NSLayoutAttribute.Width, relatedBy: NSLayoutRelation.Equal, toItem: nil, attribute: NSLayoutAttribute.NotAnAttribute, multiplier: 1, constant: contentWidth)
        let contentTop:NSLayoutConstraint = NSLayoutConstraint(item: content, attribute: NSLayoutAttribute.Top, relatedBy: NSLayoutRelation.Equal, toItem: scroll, attribute: NSLayoutAttribute.Top, multiplier: 1, constant: 0)
        let contentLeft:NSLayoutConstraint = NSLayoutConstraint(item: content, attribute: NSLayoutAttribute.Left, relatedBy: NSLayoutRelation.Equal, toItem: scroll, attribute: NSLayoutAttribute.Left, multiplier: 1, constant: contentWidth*CGFloat(i))
        scroll.addConstraints([contentHeightConstraint, contentWidthConstraint, contentTop, contentLeft])

        let imageHeight:CGFloat = contentHeight*0.90
        let imageWidth:CGFloat = contentWidth*0.90

        let thumbnail:UIImageView = UIImageView()
        content.addSubview(thumbnail)
        thumbnail.image = UIImage(named: preLoadedImageNames[i])
        thumbnail.contentMode = UIViewContentMode.ScaleAspectFit
        thumbnail.frame = CGRect(x: contentWidth/2 - imageWidth/2, y: contentHeight/2 - imageHeight/2, width: imageWidth, height: imageHeight)

        images.append(thumbnail)

        let tap:UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(ViewController.quickStartTapped(_:)))
        content.addGestureRecognizer(tap)
        self.quickStartTaps.append(tap)

        scroll.contentSize.width  = contentWidth

    }
  

Я что-то здесь делаю не так? Почему память, используемая для размещения этих изображений, не освобождается при отключении контроллера представления?

Я ценю любую помощь, которую я могу получить.

Комментарии:

1. Вы убедились, что ваш контроллер просмотра действительно отключен? Вы можете добавить deinit { } метод и убедиться.

2. @kleezy — Это была хорошая идея … и на самом деле deinit не вызывается. Я понятия не имею, почему…

3. Ищите такие вещи, как неслабые ссылки на объекты, которым принадлежит ваш контроллер просмотра, или блоки, которые ссылаются на self . Подобные вещи часто могут приводить к утечкам памяти, подобным этому. Кроме того, где бы вы ни представили свой контроллер представления, у него все еще есть переменная, которая ссылается на VC после того, как она была отклонена?

4. @kleezy — Эй, я был на самом деле неправ, deinit вызывается, он просто по какой-то причине не остановится, если я вставлю точку останова, но не выполню никакого фактического кода. Итак, я ввел простой print() вызов внутри deinit {} , и теперь я вижу, что он действительно вызывается. Таким образом, VC фактически деинициализируется, но память, выделенная для этих UIImageView файлов, не освобождается. Я чешу голову.

5. @kleezy — Чтобы ответить на ваш вопрос, с VC, который представляет контроллер представления с утечкой памяти, у меня есть переменная, которая ссылается на нее, но это необязательное значение, которое я сразу устанавливаю nil после увольнения. Итак, он настроен так var viewController: UIViewController! , а затем, после того, как я позвоню dismissViewControllerAnimated , в блоке завершения я скажу viewController = nil