我已经读过imageNamed:在尝试初始化图像时很糟糕。但那么最好的方法是什么?我正在使用imageWithContentsOfFile:并在我的资源文件夹中传递图像的路径
[UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:imageName ofType:@"jpg"]
此调用在for循环中进行了大约30次。
现在当我使用乐器运行我的应用程序时,我发现很多内存被NSString用于上面的操作,我们使用字符串文字(@“jpg”) Instruments将负责的调用者显示为[NSBundle mainBundle],当我使用字符串文字作为类型时,这又指向该行。
那么在不使用太多内存的情况下初始化图像的最有效方法是什么?
我将语句改为
img = [UIImage imageWithContentsOfFile:[bndl pathForResource:fileName ofType:extn]]
其中extn
是静态的并初始化为@"jpg"
。 fileName
在for循环的每次迭代中不断变化。但即便如此,NSString
的最大用量是由于[NSBundle mainBundle]
和[NSBundle pathForResource:OfType:]
而不是仪器。
答案 0 :(得分:5)
我会避免在循环中使用自动释放的对象。如果Instruments在NSBundle pathForResource:ofType:call上报告大量点击,我会在循环外部进行一些处理。
我建议的实现看起来像这样:
NSString *resourcePath = [[[NSBundle mainBundle] resourcePath] retain];
for (int i = 0; i < 1000; ++i)
{
...
NSString *pathForImageFile = [resourcePath stringByAppendingPathComponent:fileName];
NSData *imageData = [[NSData alloc] initWithContentsOfFile:pathForImageFile];
UIImage *image = [[UIImage alloc] initWithData:imageData];
[imageData release];
...
[image release];
}
[resourcePath release];
你将累积一个自动释放的字符串(pathForImageFile),但这不应该那么糟糕。你可以在循环中创建和释放一个自动释放池,但我建议每10或100次循环通过一次,而不是每次通过。此外,resourcePath上的保留和释放可能是多余的,但我把它放在那里,以防你想在这里的某个地方使用你自己的自动释放池。
答案 1 :(得分:2)
imageNamed:
在某些情况下很糟糕,因为它会在加载后缓存图像。因此,如果您要重新使用图片 - 您的应用包中的某些内容非常可能 - 使用imageNamed:
完全没问题。但是,如果你有很多不同的图像,并且你只是偶尔加载一个特定的图像,你会想要避免它。
如果您不想使用imageNamed:
,第一段代码就可以了。如果您担心循环中创建的临时字符串,请将其放在循环之前:
NSAutoreleasePool * pool = [NSAutoreleasePool new];
之后:
[pool release];
这将确保一旦循环退出,循环中的任何临时对象都将被释放。但是,请确保保留要保留的所有临时对象。 (例如,图像本身需要添加到将保留它们的数据结构中,例如数组,字典或集合,或手动保留。)
答案 2 :(得分:1)
您可以做的是确保在循环中释放自动释放的对象
在:
for (int i = 0; i < 1000; ++i)
{
UImage* img = [UIImage imageWithContentsOfFile:
[bndl pathForResource:fileName ofType:extn]];
...
}
后:
for (int i = 0; i < 1000; ++i)
{
NSAutoreleasePool* ap = [[NSAutoreleasePool alloc] init];
UImage* img = [UIImage imageWithContentsOfFile:
[bndl pathForResource:fileName ofType:extn]];
...
[ap release];
}
但我怀疑那些NSString实例可能会造成太多麻烦:
您确定要正确解释乐器的输出吗? 您确定代码的其他部分没有泄漏这些字符串吗? (显示的代码看起来不错)
答案 3 :(得分:0)
我还没有看到有人提到它,但是你看到由该行创建多个NSString实例的原因是因为pathForResource:ofType:必须将字符串连接在一起以创建来自各个组件的完整路径(目录名称,文件名,扩展名。)
我也坚持“不要担心”阵营。与甚至非常小的图像的内存使用相比,几十个NSString实例只是噪声。如果您的循环从30个图像变为几千个,或者某个东西,那么您可能需要考虑在循环内创建一个NSAutoreleasePool。