【问题标题】:Calling ALAssetReprsentation's metadata method several hundred times will fail调用 ALAssetReprsentation 的元数据方法几百次会失败
【发布时间】:2011-12-29 14:54:04
【问题描述】:

我正在编写一个小型 iPhone 应用程序来检索 iPhone 中存储的所有照片的元数据,例如 EXIF 信息,并在调用 Assets Library Framework API 时遇到了一个奇怪的问题。基本上,如果我调用 ALAssetRepresentation 的元数据方法(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 进行测试。我正在使用启用了 ARC(自动引用计数)的 Xcode 4.2 进行开发。而且我只能在将应用程序部署到iPhone 3GS设备时重现此问题,但在使用具有相同代码的iOS模拟器时无法重现此问题(至少我在iOS模拟器中调用API超过1800次后不会重现此问题)。

感谢任何帮助。谢谢。

【问题讨论】:

  • 你检查过是不是内存问题吗?例如。检查仪器和/或在循环内使用额外的自动释放池。
  • 我正在使用ARC,你知道如果使用ARC会出现内存问题吗?我会尽快尝试使用 Instruments 进行分析(我还不熟悉 Instruments)。谢谢。
  • ARC 与它无关。如果您在紧密循环中分配太多自动释放的对象,您仍然可能会耗尽内存。尝试像这样修改你的循环:while (i&lt;600) { @autoreleasepool { i++; metadata = [representation metadata]; NSLog(@"photo %d indexed %@", i, metadata); } }
  • @OleBegemann 非常感谢,它确实解决了我的问题。您能否用更多细节来解释它作为下面的答案?我会接受它作为这个问题的最终答案。

标签: iphone ios alassetslibrary


【解决方案1】:

您可能内存不足。 [representation metadata] 方法返回一个自动释放的对象,并可能在执行时创建更多的自动释放对象。所有这些实例都添加到自动释放池中,等待 ARP 有机会自行耗尽时最终释放(并释放它们的内存)。

问题在于,在您的代码将控制权返回给运行循环之前,这不会发生。因此,在循环期间,至少有 600 个大字典(可能还有更多对象)最终被分配而不是被释放。根据这些对象的大小,内存使用量可能会大大增加。

无论您是否使用 ARC,这都是正确的。

为避免此问题,请尝试在循环的每次迭代中创建一个新的自动释放池。这样一来,每次迭代都会耗尽 ARP:

while (i<600) {
    @autoreleasepool {
        i++;
        metadata = [representation metadata];
        NSLog(@"photo %d indexed %@", i, metadata);
    }
}

从性能角度来看,这不一定是最佳解决方案,但至少它会告诉您问题是否与内存有关。

PS:您的代码目前没有多大意义。为什么要连续检索同一资产 600 次的元数据?

【讨论】:

  • 这段代码不是我在我的应用程序中使用的真实代码,而是重现这个问题的一小段代码。在我的应用程序中,有一个枚举器迭代资产库中的所有照片,这将导致我在上面提出的相同问题。而且您提到“从性能角度来看,这不一定是最佳解决方案”,您能否告诉我其他可能的解决方案是什么?
【解决方案2】:

在此处输入代码确保您保留 ALAssetLibrary,直到您完成对相关资产的访问。来自 Apple 的文档:

从库实例返回的对象的生命周期是相关的 到库实例的生命周期。

【讨论】:

    猜你喜欢
    • 2016-02-04
    • 1970-01-01
    • 2020-09-10
    • 1970-01-01
    • 2011-07-04
    • 2018-07-06
    • 2019-04-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多