Проблема с утечкой памяти Swift UIImage .jpegData

У меня есть код, который принимает UIImage и сохраняет это изображение на диск. Этот код повторяется для нескольких изображений. Я заметил, что при каждом запуске кода у меня возникает утечка памяти, которая сохраняется до тех пор, пока представление не будет удалено.

Я отследил проблему до следующей строки: var data = image.jpegData(compressionQuality: 0.8 )

При каждом вызове этой строки под сжатое изображение выделяется соответствующий объем памяти (каждый раз ~10 Мб), и не освобождается до тех пор, пока представление не будет закрыто. Я даже пытался удалить любое использование данных (т.е. счетчик ссылок должен быть равен 0), но он все еще не освобождает память.

    func save_to_folder( tray_number: Int64, tray_type: String, image: UIImage, filename: String ) -> Bool {
        let dir = self.directory!
            .appendingPathComponent( "trays" )
            .appendingPathComponent( String( format: "tray_%04d", tray_number ) )
            .appendingPathComponent( tray_type )
        
        print( "  save_dir: \( dir.path )" )
        
        let full_filename = dir.appendingPathComponent( filename ).appendingPathExtension( "JPG" )
        print( "  full_filename: \( full_filename.path )" )
        
        do {
            try FileManager.default.createDirectory(at: dir, withIntermediateDirectories: true, attributes: nil )
        }
        catch let error {
            print( "Error creating directory: \( error )" )
            return false
        }
        
        var data = image.jpegData(compressionQuality: 0.8 )
        /*
        do {
            try data!.write(to: full_filename, options: Data.WritingOptions.atomic )
            return true
        }
        catch let error {
            print( "Failed to write file: \( error )" )
        }
        
        data = nil
 */
        return false
    }
for itt in 0...self.URLs.count - 1{
                let closure = { [weak self] in
                    print(self!.URLs[itt])
                    let image = UIImage.init(contentsOfFile: self!.URLs[itt].relativePath)
                    //temp_bore = try! Borehole(sqlite_filename:self!.borehole!.filename)
                    let _ = self?.borehole?.save_to_folder(tray_number: tray_number, tray_type: tray_type, image: image! )
                    tray_number += 1
                    progress += 1
                    DispatchQueue.main.async {
                        alertView.message = "Adding \( progress ) of \( total )"
                    }
                }
                closure()
            }

Кто-нибудь знает, что здесь происходит? Почему память, выделенная jpegData, никогда не освобождается?

Покажите часть итерации, на которую вы ссылаетесь.

El Tomato 21.12.2020 13:01

Спасибо, я добавил код итерации. Используемый объект «скважина» также выполняет кучу обработки изображения. save_to_folder является частью объекта скважины.

Hugo Coppejans 21.12.2020 13:07

Я не знаю. Попробуйте использовать autoreleasepool. Для чего вообще нужно closure()?

El Tomato 21.12.2020 13:12

Что такое скважина?.save_to_folder?

El Tomato 21.12.2020 13:13

Я возился с закрытием из-за утечки памяти, пытаясь подтвердить несколько вещей. скважина — это просто объект, который я использую для всех своих SQL-запросов и из которого я вызываю функции обработки данных. Также предполагается куча других вызовов, но я удалил их, чтобы упростить и найти утечку памяти. Таким образом, в этом случае вы можете думать о скважине как об объекте, который я использую для записи изображения на диск.

Hugo Coppejans 21.12.2020 13:21

autoreleasepool сделал свое дело, спасибо

Hugo Coppejans 21.12.2020 13:26
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
6
873
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Я нашел решение благодаря El Tomato.

Если кто-то еще столкнется с этой проблемой, добавьте autoreleasepool к вашему вызову .jpegData.

autoreleasepool{
            let data = image.jpegData(compressionQuality: 0.8 )
    
            do {
                try data!.write(to: full_filename, options: Data.WritingOptions.atomic )
            }
            catch let error {
                print( "Failed to write file: \( error )" )
            }

        }

Другие вопросы по теме