У меня проблема с iPad-приложением, в котором отображаются все изображения (все 1024x768), которые принимают 3Mo в ОЗУ, не освобождая их, когда они не нужны, что приведет к сбою через некоторое время.Память изображения не освобождается
Я загружаю изображения с использованием метода «contentOfFile», который должен (в моем понимании) освобождать память, когда память низкая, и приложение больше не нуждается в ней, но это, похоже, не так (даже когда i имитировать предупреждение памяти на симуляторе).
Я сделал действительно простой тестовый класс, чтобы проиллюстрировать проблему ниже (swift 1.2).
Когда приложение загружает его, создается представление, добавляются подслои, заполненные изображениями, а затем, когда я нажимаю на экран, я ожидаю, что 72Mo, сделанное несжатыми данными растровых изображений (используемыми Core Animation для визуализации слоя), будет освобождается (или, по крайней мере, освобождается, когда я имитирую предупреждение о памяти), чего он никогда не делает.
(Примечание: Я использую ARC как на мой основной проект и этот тестовый проект)
ViewController: UIViewController {
func tap(gesture : UITapGestureRecognizer)
{
if gesture.state == UIGestureRecognizerState.Ended {
var tmpV = self.view.viewWithTag(1000)
// tried everything to release memory
for subLayer : CALayer in tmpV?.layer.sublayers as! [CALayer!] {
subLayer.contents = nil
}
tmpV?.layer.sublayers.removeAll(keepCapacity: false)
tmpV?.removeFromSuperview()
tmpV = nil
}
}
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
//add gesture to remove images from view
var gesture = UITapGestureRecognizer(target: self, action: Selector("tap:"))
self.view.addGestureRecognizer(gesture)
//loading images
var imagesArray : [UIImage!]! = self.fillImagesArray()
//adding those images to a view
let tmpV = UIView(frame: CGRect(x: 0, y: 0, width: 1024, height: 768))
for img in imagesArray {
var layer = CALayer()
layer.frame = CGRect(x: 0, y: 0, width: 1024, height: 768)
layer.contents = img.CGImage
tmpV.layer.addSublayer(layer)
}
tmpV.tag = 1000
self.view.addSubview(tmpV)
}
func fillImagesArray() -> [UIImage!]{
var array : [UIImage!] = []
for i in 0 ... 23 {
var image : UIImage?
var filename = NSBundle.mainBundle().pathForResource("image \(i)", ofType: "png")
image = UIImage(contentsOfFile: filename!)
array.append(image)
}
return array
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}
EDIT:
Чтобы добавить еще несколько деталей, вот скриншот взят из профиля/Отчисления инструмента , так как я сказал, что догадываюсь, что память берется CA при рендеринге слоев.
Когда изображения не отображаются на экране, память по-прежнему очень низкая, но после их отображения они не освобождаются даже после удаления.
Я попытался нарисовать слой tmpV, удалить подслои, а затем добавить обрамленное изображение в tmpV.layer.contents в viewDidAppear
, и если я сделаю так, мое изображение будет правильным, а память останется низкой, но она будет стоить около 1,5 секунд для рисования слоя (мне нужно, чтобы мое приложение было быстрым, и я не могу позволить себе это время).
Единственный способ, которым я нашел освобождение памяти, заключался в том, чтобы добавить изображения в массив переменных класса и опустошить его на tap
func. Но мне нужно будет снова загрузить изображения, если я захочу заново создать изображение, и я бы хотел этого избежать.
Что заставляет вас думать: «загружать изображения с использованием метода contentOfFile», который должен (по моему мнению) выпускать память, когда память низкая, а приложение не нужно »? – zaph
Просто угадайте, исходя из чтения ответов на разные сообщения SO, такие как: http://stackoverflow.com/questions/10494980/cant-release-unused-calayer-memory-when-using-multiple-layers http: // stackoverflow.com/questions/20588338/ios-uiimage-storage-formats-memory-usage-and-encoding-decoding – GawenBerger