簡體   English   中英

iPhone中UIImage的內存分配和發布?

[英]Memory allocation and release for UIImage in iPhone?

我在iPhone中使用以下代碼來獲得較小的裁剪圖像,如下所示:

- (UIImage*) getSmallImage:(UIImage*) img
{
    CGSize size = img.size;
    CGFloat ratio = 0;
    if (size.width < size.height) {
        ratio = 36 / size.width;
    } else {
        ratio = 36 / size.height;
    }
    CGRect rect = CGRectMake(0.0, 0.0, ratio * size.width, ratio * size.height);

    UIGraphicsBeginImageContext(rect.size);
    [img drawInRect:rect];

    UIImage *tempImg = [UIGraphicsGetImageFromCurrentImageContext() retain];

    UIGraphicsEndImageContext();
    return [tempImg autorelease];
}

- (UIImage*)imageByCropping:(UIImage *)imageToCrop toRect:(CGRect)rect
{

    //create a context to do our clipping in
    UIGraphicsBeginImageContext(rect.size);
    CGContextRef currentContext = UIGraphicsGetCurrentContext();

    //create a rect with the size we want to crop the image to
    //the X and Y here are zero so we start at the beginning of our
    //newly created context

    CGFloat X = (imageToCrop.size.width - rect.size.width)/2;
    CGFloat Y = (imageToCrop.size.height - rect.size.height)/2;


    CGRect clippedRect = CGRectMake(X, Y, rect.size.width, rect.size.height);
    //CGContextClipToRect( currentContext, clippedRect);



    //create a rect equivalent to the full size of the image
    //offset the rect by the X and Y we want to start the crop
    //from in order to cut off anything before them
    CGRect drawRect = CGRectMake(0,
                                 0,
                                 imageToCrop.size.width,
                                 imageToCrop.size.height);

    CGContextTranslateCTM(currentContext, 0.0, drawRect.size.height);
    CGContextScaleCTM(currentContext, 1.0, -1.0);
    //draw the image to our clipped context using our offset rect
    //CGContextDrawImage(currentContext, drawRect, imageToCrop.CGImage);


    CGImageRef tmp = CGImageCreateWithImageInRect(imageToCrop.CGImage, clippedRect);

    //pull the image from our cropped context
    UIImage *cropped = [UIImage imageWithCGImage:tmp];//UIGraphicsGetImageFromCurrentImageContext();
    CGImageRelease(tmp);
    //pop the context to get back to the default
    UIGraphicsEndImageContext();

    //Note: this is autoreleased*/
    return cropped;
}

我在cellForRowAtIndexPath中使用以下代碼行來更新單元格的圖像:

cell.img.image = [self imageByCropping:[self getSmallImage:[UIImage imageNamed:@"goal_image.png"]] toRect:CGRectMake(0, 0, 36, 36)];

現在當我添加這個表視圖並從導航控制器彈出它時,我看到了一個內存加息。我看到沒有泄漏,但內存不斷攀升。

請注意,每行的圖像都會發生變化,我正在使用延遲初始化創建控制器,這是我創建或在需要時分配它。

我在互聯網上看到許多人面臨同樣的問題,但非常罕見的好解決方案。 我有多個視圖使用相同的方式,我看到幾乎內存在20-25視圖轉換中提升到4MB。

解決此問題的好方法是什么?

TNX。

在EndImageContext之前,您無法從例程返回:

return UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

試試這個:

UIImage* newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;

您不需要注釋掉的保留或自動釋放。

[UIImage imageNamed:]導致內存泄漏,因為它使用了圖像的內部緩存。

  • 簡單的方法是由程序員在外部緩存圖像。
    為此,使用-(UIImage*)thumbnailImage:(NSString*)fileName { UIImage *thumbnail = [thumbnailCache objectForKey:fileName]; if (nil == thumbnail) {
    NSString *thumbnailFile = [NSString stringWithFormat:@"%/%@", [[NSBundle mainBundle] pathForResource:fileName ofType:@"png"]]; //dont forget to set correct image type thumbnail = [UIImage imageWithContentsOfFile:thumbnailFile]; [thumbnailCache setObject:thumbnail forKey:fileName]; } return thumbnail; }
    -(UIImage*)thumbnailImage:(NSString*)fileName { UIImage *thumbnail = [thumbnailCache objectForKey:fileName]; if (nil == thumbnail) {
    NSString *thumbnailFile = [NSString stringWithFormat:@"%/%@", [[NSBundle mainBundle] pathForResource:fileName ofType:@"png"]]; //dont forget to set correct image type thumbnail = [UIImage imageWithContentsOfFile:thumbnailFile]; [thumbnailCache setObject:thumbnail forKey:fileName]; } return thumbnail; }

    聲明NSMutableDictionary *thumbnailCache; 在.h文件中

    並且使用可以使用此功能

    cell.img.image = [self imageByCropping:[self getSmallImage:[self thumbnailImage:@"goal_image"]] toRect:CGRectMake(0, 0, 36, 36)];

  • 清除應用程序共享緩存,即設置為nil

我認為這將解決你的問題。

根據圖像的大小,您對imageNamed:的使用可能是內存增長的原因。 這不一定是個問題。 imageNamed:用於經常加載相同圖像並由緩存支持的代碼。 在iOS 3.0之前它有泄漏,但它們已修復,如果你想利用緩存,我不知道有任何理由不使用這個API。

您應該通過Instruments運行代碼,特別是Leaks模板。 使用快照分析,您可以精確定位代碼中的位置,以便在您不期望它們時增加內存占用,即使傳統的泄漏分析錯過了這些位置。 Bill Bumgarner 撰寫了一篇討論使用快照分析的文章。 他使用Mac OS X應用程序作為他的例子,但這些技術同樣適用於iOS應用程序。

無法解決問題,但可能會導致問題:緩存縮略圖。 在36 x 36時,它們將非常小而無法記憶。 這也應該提供性能提升,因為圖形工作非常密集。

而不是使用autorelease來管理內存(據我所知,很少或根本沒有保證何時釋放內存,只是它最終會將你的用例代碼行分成三部分並管理內存)你自己。 充其量可能是解決內存泄漏所必需的一切。 至少像Instruments這樣的工具將能夠從那里獲取它並向您顯示可能產生的內存泄漏。

此外, [UIImage imageNamed:]可能很昂貴,並自動釋放圖像。 您可以使用相對簡單的圖像緩存機制替換該調用,該機制可以重用常用的請求圖像並提升性能。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM