#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