首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >理解NSAutoreleasePool

理解NSAutoreleasePool
EN

Stack Overflow用户
提问于 2014-12-06 06:16:34
回答 2查看 2.1K关注 0票数 1

我有一个应用程序,可以在iPhone 4s上使用摄像头时获得内存警告。在使用之前,我会缩放图像。

代码语言:javascript
复制
+ (UIImage*)simpleImageWithImage:(UIImage*)image scaledToSize:(CGSize)newSize
{

// Create a graphics image context
UIGraphicsBeginImageContext(newSize);

// Tell the old image to draw in this new context, with the desired
// new size
[image drawInRect:CGRectMake(0,0,newSize.width,newSize.height)];

// Get the new image from the context
UIImage* newImage = UIGraphicsGetImageFromCurrentImageContext();

// End the context
UIGraphicsEndImageContext();


// Return the new image.
return newImage;
}

我读到你应该从这里开始使用NSAutoreleasePool http://wiresareobsolete.com/2010/08/uiimagepickercontroller/

所以我对代码做了如下修改:

代码语言:javascript
复制
+ (UIImage*)simpleImageWithImage:(UIImage*)image scaledToSize:(CGSize)newSize
{
//http://wiresareobsolete.com/2010/08/uiimagepickercontroller/

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

// Create a graphics image context
UIGraphicsBeginImageContext(newSize);

// Tell the old image to draw in this new context, with the desired
// new size
[image drawInRect:CGRectMake(0,0,newSize.width,newSize.height)];

// Get the new image from the context
UIImage* newImage = UIGraphicsGetImageFromCurrentImageContext();

// End the context
UIGraphicsEndImageContext();

[newImage retain];

[pool release];

// Return the new image.
return newImage;
}

记忆警告消失了。我并没有在一个单独的线程上调用它。这个NSAutoreleasePool在做什么?我只是不明白。

我能否在本地NSAutoreleasePool中保留一个对象?

在释放NSAutoreleasePool之后,我能使用保留的对象吗?

的一个重要问题:,如何帮助我的应用程序的内存占用,使它不会收到内存警告?

EN

回答 2

Stack Overflow用户

发布于 2014-12-09 07:54:36

首先,您应该使用@autoreleasepool块而不是NSAutoreleasePool对象;后者非常过时。前者更好,因为当您离开块的作用域时,它会自动耗尽池,而不需要自己显式地执行。

自动释放池只记得在其范围内“自动释放”的内容,并在池被耗尽时释放它们。“自动释放”对象就像释放对象,但是延迟了;从内存管理的角度来看,它需要一个强大的引用,并将它“传输”到池中,这样池现在就有了对对象的强大引用,而您就没有了。在“自动释放”中,如果一个方法(其名称不是以newcopy开头)需要返回在函数期间创建的对象,那么它几乎必须自动释放。通过将其放在池中,它保证对象将是活动的,将被调用函数接收。在您的代码中,UIGraphicsGetImageFromCurrentImageContext()可能会返回一个自动释放的对象。

自动释放池只在池的末尾排出。池中的对象在池期间保持活动(因为它们实际上是由池“拥有”的)。这意味着如果池持续了很长时间,并且有很多东西被自动释放在它上,那么很多对象就会被阻止被释放,这可能是不好的。

例如,假设函数的一次运行自动释放一个对象(即UIGraphicsGetImageFromCurrentImageContext()返回的对象)。然后,如果您在一个循环中运行了100,000次函数,那么就会有100,000个对象留在内存中,因为它们会被放到一个尚未有机会耗尽的池中。但是,如果将另一级别的池放入循环的每一次迭代中,它将在每次迭代结束时耗尽,从而阻止对象的积累。

至于第二段代码,在simpleImageWithImage:方法中放置一个自动释放池可以捕获来自UIGraphicsGetImageFromCurrentImageContext()的自动发布。但是,您还有另一个问题,因为为了从simpleImageWithImage: 方法本身返回图像对象,需要自动释放它

编写的方法违反了内存管理规则。您的方法返回一个保留的对象,调用方必须记住才能释放该对象。但是,调用者并不知道这是基于名称。根据命名约定,唯一能够返回保留实例的方法是名称以allocretainnewcopymutableCopy开头的方法。您的方法没有从任何这些开始,所以它必须返回一个非保留的实例。由于您拥有该对象(通过保留它),您必须执行平衡释放或自动释放。您不能释放它,因为它会导致对象可能被释放,因为它没有其他的强引用,所以只能自动释放它。

但是,如果您要再次自动发布它,那么在这里添加一个自动释放池将一无所获,除非是在drawInRect:UIGraphicsGetImageFromCurrentImageContext()内部,否则它们会自动释放大量内容。

票数 7
EN

Stack Overflow用户

发布于 2014-12-06 06:54:09

您自己创建的NSAutoreleasePool只调用从NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];[pool release];的区域内的自动释放对象的发布方法,

这里

代码语言:javascript
复制
UIImage* newImage = UIGraphicsGetImageFromCurrentImageContext();

newImage是一个自动释放对象,[newImage release]将在[pool release];之后被调用

如果不是,[newImage retain]; newImage将在[pool release];之后去分配

  1. 可以在本地NSAutoreleasePool中保留对象。
  2. 您可以在释放NSAutoreleasePool之后使用保留的对象。
  3. 使用NSAutoreleasePool释放临时内存。
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/27328930

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档