我有一个应用程序,可以在iPhone 4s上使用摄像头时获得内存警告。在使用之前,我会缩放图像。
+ (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/
所以我对代码做了如下修改:
+ (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之后,我能使用保留的对象吗?
的一个重要问题:,如何帮助我的应用程序的内存占用,使它不会收到内存警告?
发布于 2014-12-09 07:54:36
首先,您应该使用@autoreleasepool块而不是NSAutoreleasePool对象;后者非常过时。前者更好,因为当您离开块的作用域时,它会自动耗尽池,而不需要自己显式地执行。
自动释放池只记得在其范围内“自动释放”的内容,并在池被耗尽时释放它们。“自动释放”对象就像释放对象,但是延迟了;从内存管理的角度来看,它需要一个强大的引用,并将它“传输”到池中,这样池现在就有了对对象的强大引用,而您就没有了。在“自动释放”中,如果一个方法(其名称不是以new或copy开头)需要返回在函数期间创建的对象,那么它几乎必须自动释放。通过将其放在池中,它保证对象将是活动的,将被调用函数接收。在您的代码中,UIGraphicsGetImageFromCurrentImageContext()可能会返回一个自动释放的对象。
自动释放池只在池的末尾排出。池中的对象在池期间保持活动(因为它们实际上是由池“拥有”的)。这意味着如果池持续了很长时间,并且有很多东西被自动释放在它上,那么很多对象就会被阻止被释放,这可能是不好的。
例如,假设函数的一次运行自动释放一个对象(即UIGraphicsGetImageFromCurrentImageContext()返回的对象)。然后,如果您在一个循环中运行了100,000次函数,那么就会有100,000个对象留在内存中,因为它们会被放到一个尚未有机会耗尽的池中。但是,如果将另一级别的池放入循环的每一次迭代中,它将在每次迭代结束时耗尽,从而阻止对象的积累。
至于第二段代码,在simpleImageWithImage:方法中放置一个自动释放池可以捕获来自UIGraphicsGetImageFromCurrentImageContext()的自动发布。但是,您还有另一个问题,因为为了从simpleImageWithImage: 方法本身返回图像对象,需要自动释放它!
编写的方法违反了内存管理规则。您的方法返回一个保留的对象,调用方必须记住才能释放该对象。但是,调用者并不知道这是基于名称。根据命名约定,唯一能够返回保留实例的方法是名称以alloc、retain、new、copy和mutableCopy开头的方法。您的方法没有从任何这些开始,所以它必须返回一个非保留的实例。由于您拥有该对象(通过保留它),您必须执行平衡释放或自动释放。您不能释放它,因为它会导致对象可能被释放,因为它没有其他的强引用,所以只能自动释放它。
但是,如果您要再次自动发布它,那么在这里添加一个自动释放池将一无所获,除非是在drawInRect:或UIGraphicsGetImageFromCurrentImageContext()内部,否则它们会自动释放大量内容。
发布于 2014-12-06 06:54:09
您自己创建的NSAutoreleasePool只调用从NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];到[pool release];的区域内的自动释放对象的发布方法,
这里
UIImage* newImage = UIGraphicsGetImageFromCurrentImageContext();newImage是一个自动释放对象,[newImage release]将在[pool release];之后被调用
如果不是,[newImage retain]; newImage将在[pool release];之后去分配
NSAutoreleasePool释放临时内存。https://stackoverflow.com/questions/27328930
复制相似问题