2015-10-31 2 views
-1

Я вижу большую утечку памяти при создании изображений путем визуализации невидимого представления в контексте. Я сократил его до самой базовой реализации и определил две строки кода, которые способствуют утечке памяти: renderInContext и UIImagePNGRepresentation. Если я прокомментирую обоим, утечки не произойдет, но если один из них раскоментирован, произойдет утечка, если обе раскоментированы, произойдет два утечки. Каждый раз, когда использует метод ниже, использование памяти значительно увеличивается (как и ожидалось), а затем через некоторое время оно уменьшается, но на 0,8 МБ выше, чем сумма, которая была до вызова.Утечка памяти с renderInContext и UIImagePNGRпредставляет

Как я могу решить эту проблему, чтобы не было утечек памяти?

public class func imageDataForSymbol(symbol: String) -> NSData? { 
    var imageData: NSData! 

    let dimension = 180 

    let label = UILabel(frame: CGRectMake(0, 0, CGFloat(dimension), CGFloat(dimension))) 
    label.text = symbol 

    let colorSpace = CGColorSpaceCreateDeviceRGB() 
    let bitmapInfo = CGImageAlphaInfo.PremultipliedLast.rawValue 
    let bitmapContext = CGBitmapContextCreate(nil, dimension, dimension, 8, 0, colorSpace, bitmapInfo)! 

    label.layer.renderInContext(bitmapContext) //FIXME: causing leak!! 

    let cgImage = CGBitmapContextCreateImage(bitmapContext)! 
    let image = UIImage(CGImage: cgImage) 
    imageData = UIImagePNGRepresentation(image)! //FIXME: causing leak!! 

    return imageData 
} 

Чтобы проверить это, в viewDidAppear:

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 
    dispatch_async(dispatch_get_global_queue(QOS_CLASS_UTILITY, 0), ^{ 
     NSData *d = [ImageGenerator imageDataForSymbol:@"W"]; 

     dispatch_async(dispatch_get_main_queue(), ^{ 
      NSLog(@"triggered"); 
     }); 
    }); 
}); 

Если есть лучший способ создать NSData для Образом UILabel «s layer, я все для этого. Я не мог придумать другой способ его получить, кроме создания CIImage от CGImage, затем от CIImage до UIImage, затем от UIImage до NSData. Обратите внимание, что он не должен быть быстрым, но ему нужно создать изображение в фоновом потоке, чтобы пользовательский интерфейс оставался чувствительным к дополнительным вводам.

+0

Использование Simulator @ Matt, попытается режим выхода на IPad в немного и доложить! Это не так странно, как кажется, я делаю больше причудливых вещей, кроме одного ярлыка, это урезанный код, который показывает утечки. Я бы просто сделал это так, как обычно, но возиться с UIKit в фоновом потоке - это большой нет-нет, и мне нужно, чтобы приложение продолжало реагировать, когда это происходит. – Joey

+0

@matt Подход 'UIGraphicsBeginImageContext' был подход, который я взял изначально, но это не должно выполняться в фоновом потоке, и я не могу запустить его в основном потоке - см. Вопрос, связанный ниже. Подход, который я сейчас принимаю, - это подход, показанный в ответе: вместо этого используйте Core Graphics. http://stackoverflow.com/questions/12843777/renderincontext-memory-leak-if-not-use-on-main-thread/ – Joey

+0

Рендеринг метки в контексте UIGraphics в фоновом потоке не работает ... текст не появляется. http://stackoverflow.com/questions/30512053/swift-uilabel-text-not-renderer-when-using-renderincontext-asynchronously – Joey

ответ

-1

пара CGColorSpaceCreateDeviceRGB с CGColorSpaceRelease

пара CGBitmapContextCreate с CGContextRelease

пара CGBitmapContextCreateImage с CGContextRelease

+1

Не в Swift - он управляет памятью для вас. – matt

+1

Технически, Swift не управляет памятью, это ARC, который делает тяжелую работу ... –

+0

Действительно? Но в Obj-C с ARC я всегда использую функции * Release, и они работают нормально. Как я помню, ARC не управляет памятью для Core Foundation. –