我有一个生成UIImage的类方法,如下所示:
+ (UIImage*)imageWithFileName:(NSString*)imgFile {
UIImage *img = nil;
NSBundle *appBundle = [NSBundle mainBundle];
NSString *resourcePath = [appBundle pathForResource:imgFile ofType:nil];
if (resourcePath != nil) {
NSURL *imageURL = [NSURL fileURLWithPath:resourcePath];
NSData *data = [[NSData alloc] initWithContentsOfURL:imageURL];
img = [UIImage imageWithData:data]; // should be autoreleased!!
[data release];
}
return img;
}
然而,当我使用它时,图像数据永远不会被释放。这肯定有一个内存错误,虽然我没有违反我所知道的任何内存管理规则。我的猜测是,因为这是一个从实例方法调用的类方法,所以没有活动的自动释放池,或者只是在我退出应用程序时才会耗尽。那可能是对的吗?
答案 0 :(得分:3)
将数据传递到img
后,它就会失控。 UIImage可能会在其内部实现中保留原始数据。但没关系。从您的角度来看,您已适当地发布了data
,并且完全取决于img
来确定是否希望将其保留。
您是否明确保留了返回的UIImage?或者将它传递给另一个班级?例如,如果您将其放入UIView,视图将保留img
,直到不再需要它为止。
关于你的明确问题:有一个主要的运行循环AutoreleasePool。它通常会在每个事件循环后耗尽。
答案 1 :(得分:2)
UIImage会保留图像数据,因此如果您实际上是在泄漏内存,则应检查是否释放了返回的图像。
数据变量保留计数为:
所以直到img没有被释放,提供的数据才被释放(这是有意义的,因为图像需要数据)
您可以使用retaincount来检查NSObject派生项目的当前保留计数
答案 2 :(得分:1)
我认为真正的问题是,你如何衡量内存未被释放。
自动释放池都与您所在的线程和runloop相关 - 因为它们在调用一直返回主runloop时释放内存。无论你是在调用类方法还是实例方法甚至是C函数,自动释放在所有情况下都会起作用。
我知道在您的测试中您发现存在差异,但是如果您看到其他原因之间存在差异,那么简单地说 - 因为如果您在同一个runloop中,自动释放在整个系统中的工作方式与释放内存的效果相同
答案 3 :(得分:0)
经过一些测试后我发现,问题确实与Autorelease Pools有关。如果我在实例方法中使用完全相同的代码,那绝对没有问题。
但是只要我在类方法中使用它,自动释放的UIImage对象永远不会被释放。无论自动释放池堆栈的自动释放池是类方法中最顶层的,它与实例方法严重不同。我很确定现在类方法会收到一个非常低级别的自动释放池,只有在应用程序退出时才会耗尽或释放。
所以要小心在类方法中做自动释放的东西。当然,在本地创建ARP并没有任何帮助,因为您可能需要(就像我在这种情况下所做的那样)是返回一个自动释放的对象。
我将我的代码更改为+ newImageWithFileName:并返回一个非自动释放的对象,因此接收器必须释放它或者可以发送-autorelease。
我希望有人可以提供有关此问题的更多详细信息。