2015-10-31 47 views
-1

我看到一个巨大的内存泄漏时,通过渲染一个不可见的视图到上下文创建图像。我已经将它简化为最基本的实现,并确定了导致内存泄漏的两行代码:renderInContextUIImagePNGRepresentation。如果我将两者都评论出来,则不会发生泄漏,但如果其中一个未注释,则会发生泄漏,如果两者均未注释,则会发生两处泄漏。 每次调用下面的方法时,内存使用量会显着增加(如预期的那样),然后一段时间后会下降,但比调用前高出约0.8 MB。内存泄漏renderInContext和UIImagePNGRepresentation

如何解决这个问题以确保没有内存泄漏?

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"); 
     }); 
    }); 
}); 

如果有更好的方式来为UILabellayer的图像创建NSData,我完全赞成。我想不出有什么不同的方式来获得它,除了创建CIImageCGImage然后从CIImageUIImage然后从UIImageNSData。请注意,它不需要很快,但它确实需要在后台线程上创建图像,以确保UI保持对其他输入的响应。

+0

@马特使用模拟器,将尝试在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

真的吗?但是在使用ARC的Obj-C中,我总是使用* Release函数,并且它们工作正常。我记得,ARC不会为Core Foundation管理内存。 –