2016-02-26 59 views
3

我正在使用過程映像的應用程序。這就像用戶在最多4張圖片上下載並根據用戶選擇的模板佈局它們。最終視圖中可能會添加一個圖像2-3次。保留NSImage drawInRect和NSView cacheDisplayInRect內存

佈局中的每個圖像都在NSView中繪製(使用drawInRect方法的NSView的drawRect方法)。現在通過將NSView保存爲Image來創建最終圖像(通過佈置所有圖像的組合圖像),並且一切運行良好。

現在我面臨的問題是內存被所有處理完成後應用程序保留。我使用過儀器分配,並且沒有看到內存泄漏,但是我看到「持續字節數」隨着每次應用程序會議和一個用戶報告的問題持續增加。請看截圖。

Instruments memory usage ImageIO_TIFF 當我在儀器進一步調查,我看到下面的應用程序代碼的捕捉是導致內存保留期限。所有都與ImageIO和coreImages相關。從儀器見下圖:

Instruments code snap

然而,這似乎是唯一的問題,10.10及以上系統。在10.9.x中測試了相同版本的應用程序,內存使用率仍保持在60MB。在應用會話執行過程中,它會達到200MB,但一旦完成,它會回到50-60MB,通常適用於各種應用。

[_photoImage drawInRect: self.bounds fromRect: NSZeroRect operation: NSCompositeSourceOver fraction: 1.0 respectFlipped: YES hints: nil]; 
      _photoImage = nil; 

上面,我是用繪製圖像在圖像中顯示的NSView的drawRect方法和代碼的代碼被用於獲取的NSView爲圖像。

更新:後,我進一步調查,我發現它的CGImageSourceCreateWithData被緩存NSImage中的TIFF數據。更多有史以來我使用下面的代碼來裁剪圖像,如果我取消註釋它內存消耗正常工作。

NSData *imgData = [imageToCrop TIFFRepresentation]; 
CGImageSourceRef source = CGImageSourceCreateWithData((CFDataRef)imgData, NULL); 
CGImageRef maskRef = CGImageSourceCreateImageAtIndex(source, 0, NULL); 
CGImageRef imageRef = CGImageCreateWithImageInRect(maskRef, rect); 
NSImage *cropped = [[NSImage alloc] initWithCGImage: imageRef size:rect.size]; 

CGImageRelease(maskRef); 
CGImageRelease(imageRef); 
CFRelease(source); 
//CFRelease(options); 
imgData = nil; 

我也試圖明確設置kCGImageSourceShouldCache假(但它默認爲false),但相同的結果。 請幫助解決內存保留問題。

+0

看起來我已經問過一些很容易理解或很難回答的問題。 :(請幫助,我真的卡住了。 –

回答

0

最後經過大量調試後發現,CGImageSourceCreateWithData是保存NSImage的TIFF數據的地方。當我改變了這一行:

CGImageSourceRef source = CGImageSourceCreateWithData((CFDataRef)imgData, NULL); 

CGImageSourceRef source = CGImageSourceCreateWithURL((CFURLRef)[NSURL fileURLWithPath:path], NULL); 

一切剛剛開始工作的罰款和應用程序的內存使用量下降了300MB,從(爲6個圖像)到50-60MB,它現在是一致的行爲。

除了以上改變,它仍然引起記憶保持的地方,從而擺脫的是,所有的處理完成後,我清除每一層的圖像「零」和作品般的魅力。我的印象是讓父母成爲'無'也會發布圖片,但那不起作用。

無論如何,如果任何人似乎與drawInRect或cacheDisplayInRect問題,然後確保清除圖像,如果不需要稍後。

更新2016年7月2日

我發現kCGImageSourceShouldCache默認情況下在32位虛實64位。通過將它設置爲false,我能夠通過下面的代碼釋放內存。

const void *keys[] = { kCGImageSourceShouldCache}; 
    const void *values[] = { kCFBooleanFalse}; 
    CFDictionaryRef optionsDictionary = CFDictionaryCreate(NULL, keys, values, 1, NULL, NULL); 

    CGImageSourceRef source = CGImageSourceCreateWithData((__bridge CFDataRef)[image TIFFRepresentation], optionsDictionary); 

希望它有助於某人。