Сделайте несколько скриншотов UIView без перегрузки памяти

#arrays #swift

#массивы #быстрый #swift

Вопрос:

Я делаю несколько скриншотов представления с анимированным GIF, а затем конвертирую массив скриншотов в видео. Хотя иногда это работает, я часто получаю ошибку Terminated due to memory issue . Поэтому я ищу способ, который менее нагружает память.

Текущий код

 func setUpGIF(postStory: Bool){
    print("setUpGIF (limit)")
    var frameCount: Int = 0
    UIGraphicsBeginImageContextWithOptions(self.storySize, self.canvasView.isOpaque, 0.0)
    self.canvasView.drawHierarchy(in: CGRect(x: 0, y: 0, width: self.storySize.width, height: self.storySize.height), afterScreenUpdates: false)
    let snapshotImageFromMyView = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()
    gifStoryPreview = snapshotImageFromMyView
    while frameCount != limit {
        autoreleasepool {
            frameCount = frameCount   1
            UIGraphicsBeginImageContextWithOptions(self.storySize, self.canvasView.isOpaque, 0.0)
            self.canvasView.drawHierarchy(in: CGRect(x: 0, y: 0, width: self.storySize.width, height: self.storySize.height), afterScreenUpdates: false)
            let snapshotImageFromMyView = UIGraphicsGetImageFromCurrentImageContext()
            UIGraphicsEndImageContext()
            gifImageArray.append(snapshotImageFromMyView!)
        }
    }
    autoreleasepool {
        writeImagesAsMovie(postStory: postStory, allImages: gifImageArray)
    }
}
  

Ответ №1:

Я не уверен в влиянии на память от создания и завершения всех этих графических контекстов, но наиболее очевидной причиной чрезмерного использования памяти здесь является то, что вы накапливаете кучу потенциально больших изображений в массиве. Все эти изображения находятся в памяти одновременно, поэтому в зависимости от того, сколько их и насколько они велики, вы можете использовать много памяти только для их хранения.

Вы могли бы рассмотреть возможность записи изображений во временные файлы сразу после их создания и сохранить только имена файлов в массиве. Это позволило бы избежать одновременного хранения всех изображений в памяти, но при этом сохранить их доступными. Затем при вызове writeImagesAsMovie вы можете использовать файлы один за другим, опять же убедившись, что не загружаете все изображения сразу.

Для других возможностей вам нужно будет профилировать свой код и точно видеть, где используется память. Если вы поставите точку останова в начале этого кода, вы сможете переходить по ней по одной строке за раз. Если вы сравните это с тем, что вы видите в навигаторе отладки Xcode, вы можете точно увидеть, какие строки кода вызывают дополнительное использование памяти. Это может увеличиваться и уменьшаться, поэтому не думайте, что первый всплеск обязательно является проблемой. Продолжайте, чтобы получить представление о том, где использование памяти увеличивается и остается на прежнем уровне.

Выбор раздела памяти в навигаторе отладки Xcode

Если это не поможет, вероятно, поможет использование инструментов. Инструменты обучения — это больше, чем можно легко охватить в ответе Stack Overflow, но это полезный навык, и не только в этом случае.

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

1. Идеальная логика! Спасибо!