2015-10-31 87 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管理內存。 –