将 uiimage 设置为 nil 不会使用 ARC 释放内存

Posted

技术标签:

【中文标题】将 uiimage 设置为 nil 不会使用 ARC 释放内存【英文标题】:Setting uiimage to nil doesn't release memory with ARC 【发布时间】:2011-11-02 07:46:19 【问题描述】:

我有一个滚动视图,可以在滚动页面时显示不同的图像,例如 PhotoScroller。我正在使用 ARC。当有人滚动到另一个页面时,我将当前未显示的 UIImageView 的图像属性设置为 nil,因为(试图)避免内存崩溃,这种情况仍在发生。然后当用户滚动到一个新页面时,该页面的图像设置为 UIImageView 的图像属性,以及它之前和之后的页面(为了流畅查看)。页面的 UIImage 都保存在一个数组中。然而,当我滚动页面时,内存使用量不断上升,好像将 UIImageView 的 image 属性设置为 nil 并没有从内存中释放它。我使用initWithContentsOfFile 来初始化我的 UIImages。我也尝试了imageNamedimageWithContentsOfFile,但没有运气。这是我的滚动视图代码:

- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView int indexShown = self.scrollView.bounds.origin.x / kScrollObjWidth;

for(NSNumber *index in indexesToRemove)

    UIImageView *imgViewToRemove = [[self.scrollView subviews] objectAtIndex:[index intValue]];
    imgViewToRemove.image = nil;

[indexesToRemove removeAllObjects];

UIImageView *imgViewToReplace = [[self.scrollView subviews] objectAtIndex:indexShown];
[imgViewToReplace setImage:[pageUIImagesArr objectAtIndex:indexShown]];
[indexesToRemove addObject:[NSNumber numberWithInt:indexShown]];

if(indexShown != 0 && ![[[self.scrollView subviews] objectAtIndex:indexShown-1] image])

    imgViewToReplace = [[self.scrollView subviews] objectAtIndex:indexShown-1];
    [imgViewToReplace setImage:[pageUIImagesArr objectAtIndex:indexShown-1]];
    [indexesToRemove addObject:[NSNumber numberWithInt:indexShown-1]];

if(indexShown != kNumImages-1 && ![[[self.scrollView subviews] objectAtIndex:indexShown+1] image])

    imgViewToReplace = [[self.scrollView subviews] objectAtIndex:indexShown+1];
    [imgViewToReplace setImage:[pageUIImagesArr objectAtIndex:indexShown+1]];
    [indexesToRemove addObject:[NSNumber numberWithInt:indexShown+1]];


currentView = [[self.scrollView subviews] objectAtIndex:indexShown];
//check which view is being shown`

【问题讨论】:

我发现图像的创建方式有很大的不同。而不是 [UIImage imageNamed:xxxxx];我使用 NSString *filePath = [[NSBundle mainBundle] pathForResource:imageFileNameTemp ofType:@"png"]; UIImage *image = [[UIImage alloc] initWithContentsOfFile:filePath];这节省了我大约 50% 的 Live Bytes 和 #Living 对象。我使用分配工具进行了检查。不使用静态初始化器时,您没有看到更好的结果,这让我感到困惑。 【参考方案1】:

页面的 UIImage 都保存在一个数组中。

当您将UIImageView 的属性设置为nil 时,UIImage 不会被释放,因为数组仍然持有对它们的引用。至于内存增长,可能是正在分配的其他东西。我建议您查看 Instrument 的对象分配工具,以跟踪滚动时的具体增长情况。

【讨论】:

嗯。但是当应用程序启动时,我将 uiimages 加载到数组中。我只将它们设置为 uiimageview 的图像属性,然后将其设置回 nil。我想如果它来自阵列,它只会在启动时崩溃。我确实检查了仪器,每次显示尚未显示的新图像时,内存使用量都会增加约 4 MB。 重新显示已经显示的图像时,它会停止增长吗? 是的,它只在最初加载时才会增长。这就是让我困惑的地方。 对于任何想知道的人,我最终所做的是将 uiimages 数组替换为包含图像路径的 nsstrings 数组,然后在我需要它们时加载图像,这样当我在处理完它们后将它们设置为 nil,没有对它们持有任何引用。

以上是关于将 uiimage 设置为 nil 不会使用 ARC 释放内存的主要内容,如果未能解决你的问题,请参考以下文章

将 UIImage 添加到数组后,NSMutableArray 返回 nil

使用 PHImageManager 时,PHAsset 返回 UIImage 的 nil 值

无法设置 UIImage,总是返回 nil

UIImageView 的 UIImage 为 nil

NSBundle UIImage nil iOS 7 特定

UIImage 不保存到相机胶卷