У меня есть код, который принимает 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, никогда не освобождается?
Спасибо, я добавил код итерации. Используемый объект «скважина» также выполняет кучу обработки изображения. save_to_folder является частью объекта скважины.
Я не знаю. Попробуйте использовать autoreleasepool
. Для чего вообще нужно closure()?
Что такое скважина?.save_to_folder?
Я возился с закрытием из-за утечки памяти, пытаясь подтвердить несколько вещей. скважина — это просто объект, который я использую для всех своих SQL-запросов и из которого я вызываю функции обработки данных. Также предполагается куча других вызовов, но я удалил их, чтобы упростить и найти утечку памяти. Таким образом, в этом случае вы можете думать о скважине как об объекте, который я использую для записи изображения на диск.
autoreleasepool
сделал свое дело, спасибо
Я нашел решение благодаря 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 )" )
}
}
Покажите часть итерации, на которую вы ссылаетесь.