设置UIImage:如果已在scrollview外部引用,则scrollview中的nil不会释放内存

时间:2014-02-13 02:56:52

标签: objective-c memory-management uiscrollview uiimage automatic-ref-counting

这是我的应用程序的功能。

  1. 启动时从服务器请求大约100张图像。它存储 在模型对象中的那些图像,我们称之为modelObject.storedImage
  2. modelObject还有viewObject,这是UIImageView子类
  3. 该应用有一个2D滚动视图,可将所有100个viewObject设置为子视图,在任何给定时间内滚动视图内容区域中最多显示16个
  4. 滚动到指定区域时,它会从相应的区域中找到16个图像 modelObject.storedImage并且确实

    modelObject.viewObject.image = modelObjects.storedImage;  
    
  5. 当viewObject滚出内容区域时,它将从视图中清除

    [modelObject.viewObject setImage:nil]; 
    [modelObject.viewObject removeFromSuperview];
    
  6. 问题是,尽管有清除,但当您滚动到scrollview内容区域的新区域时,内存会不断增长。将以前的modelObject.viewObject.image放在滚动视图上的内存不会被释放。因此,如果您滚动到足够的新区域,内存使用就会失控。

    要明确的是,当应用程序首次将100个图像加载到modelObject.storedImage时,内存不会失控。此外,如果我发表评论

    //modelObject.viewObject.image = modelObjects.storedImage;  
    

    然后内存也保持正常(但当然滚动视图子视图不显示任何图像)。

    我确实看到了这个问题“Setting uiimage to nil doesn't release memory with ARC”,但我认为这有所不同,因为在我的应用中,我无法继续从服务器反复请求图像。一旦被请求,他们必须坐在modelObject.storedImage,并且在相应的viewObject滚动到的时候随时可以显示。

    肯定有办法告诉ARC为这些零图像释放内存吗?在此先感谢您的帮助!

2 个答案:

答案 0 :(得分:0)

  1. 如果图像是由imageNamed:创建的,那么无法手动释放内存,您可以通过imageWithContentsOfFile对其进行优化,这要归功于您使用的是服务器图像,我认为您使用了{{1 }}。 :)
  2. 您可以尝试在滚动方法中使用imageWithContentsOfFile来实时释放内存。
  3. 您可以尝试发布viewObject而不是removeFromSuperview,也许你应该存储的是viewFrame而不是viewObject。
  4. 希望为你提供帮助。

答案 1 :(得分:0)

所以我解决了这个问题并将其作为解决方案。我很想知道是否有人有更强大的想法。我复制了图像并在scrollview上设置了副本。现在,当我清除该副本时,它的内存实际上已经释放(谢谢!!),而原始图像仍然可以舒适地放在模型中。注意,它不能简单地复制图像的CGImage并复制它,在这种情况下内存没有释放。我必须使用UIGraphicsImageContext制作新副本。

在Scrollview上设置图像的代码:

    UIImage *imageToCopy = modelObject.imageStore;
    CGSize size = imageToCopy.size;

    UIGraphicsBeginImageContext(size);
    [imageToCopy drawInRect:CGRectMake(0, 0, imageToCopy.size.width, imageToCopy.size.height)];
    UIImage *copiedImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    [modelObject.viewObject setImage:copiedImage];

当代码离开scrollview的内容区域时清除代码:

    [modelObject.viewObject setImage:nil];
    [modelObject.viewObject removeFromSuperview];

唯一的问题是绘制这些图像上下文会占用大量内存,所以我添加了这个修改以使绘图更小:

    ...
    CGSize size = imageToCopy.size;
    size.width *= .2;
    size.height *= .2;

    UIGraphicsBeginImageContext(size);
    [imageToCopy drawInRect:CGRectMake(0, 0, imageToCopy.size.width*.2, imageToCopy.size.height*.2)];
    ...