我正在编写一个小型iPhone应用程序来检索存储在iPhone中的所有照片的元数据,例如EXIF信息,并在调用Assets Library Framework API时遇到了一个奇怪的问题。基本上,如果我调用ALAssetReprsentation的元数据方法(http://developer.apple.com/library/ios/documentation/AssetsLibrary/Reference/ALAssetRepresentation_Class/Reference/Reference.html#//apple_ref/occ/instm/ALAssetRepresentation/metadata)几百次(即使对于相同的ALAssetReprsentation对象),API将报告错误并返回null而不是照片的元数据。
以下是重现此问题的代码:
ALAsset *photo = ... // fetch a photo asset via Assets Library Framework
int i = 0;
ALAssetRepresentation *representation = [photo defaultRepresentation];
NSDictionary *metadata;
while (i<600) {
i++;
metadata = [representation metadata];
NSLog(@"photo %d indexed %@", i, metadata);
}
以下是上述代码的输出。在输出的开头,一切都还可以,但是在500次之后,元数据API将报告错误,如“ImageIO:CGImageSourceCreateWithData data parameter is nil”。
...
2011-12-29 21:46:17.106 MyApp[685:707] photo 578 indexed {
ColorModel = RGB;
DPIHeight = 72;
DPIWidth = 72;
...
}
...
ImageIO: <ERROR> CGImageSourceCreateWithData data parameter is nil
2011-12-29 21:46:17.151 MyApp[685:707] photo 579 indexed (null)
ImageIO: <ERROR> CGImageSourceCreateWithData data parameter is nil
2011-12-29 21:46:17.177 MyApp[685:707] photo 580 indexed (null)
我正在使用iOS 5.0.1测试iPhone 3GS。我正在开发Xcode 4.2并启用ARC(自动引用计数)。我只能在将应用程序部署到iPhone 3GS设备时重现此问题,但在使用具有相同代码的iOS模拟器时无法重现此问题(至少我在iOS模拟器中调用API超过1800次后无法重现此问题)。
感谢任何帮助。感谢。
答案 0 :(得分:6)
您可能内存不足。方法[representation metadata]
返回一个自动释放的对象,并可能在执行时创建更多自动释放的对象。所有这些实例都被添加到自动释放池中,当ARP有机会耗尽时,等待最终释放(并释放它们的内存)。
问题是在代码将控制权返回到运行循环之前不会发生这种情况。因此,在循环的持续时间内,至少有600个大字典(可能还有更多的对象)最终被分配而不是被解除分配。根据这些对象的大小,内存使用量会大大增加。
无论您是否使用ARC,都是如此。
要避免此问题,请尝试在循环的每次迭代中创建一个新的自动释放池。这样,每次迭代都会耗尽ARP:
while (i<600) {
@autoreleasepool {
i++;
metadata = [representation metadata];
NSLog(@"photo %d indexed %@", i, metadata);
}
}
从性能角度来看,这不一定是最佳解决方案,但至少会告诉您问题是否与内存有关。
PS:你的代码目前没有多大意义。为什么要连续600次检索相同资产的元数据?
答案 1 :(得分:0)
在此输入代码确保在完成访问相关资产之前保留ALAssetLibrary。来自Apple的文档:
从库实例返回的对象的生命周期是相互关联的 到库实例的生命周期。