4

iPhoneに保存されているすべての写真のEXIF情報などのメタデータを取得するために、小さなiPhoneアプリを作成していますが、Assets LibraryFrameworkAPIを呼び出すときに奇妙な問題が発生しました。基本的に、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データパラメーターは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)

iOS5.0.1を搭載したiPhone3GSでテストしています。そして、ARC(自動参照カウント)を有効にしたXcode4.2で開発しています。また、この問題はiPhone 3GSデバイスにアプリをデプロイする場合にのみ再現できますが、同じコードでiOSシミュレーターを使用する場合は再現できません(少なくとも、iOSシミュレーターでAPIを1800回以上呼び出した後はこの問題を再現しません)。

どんな助けでも大歓迎です。ありがとう。

4

2 に答える 2

6

メモリが不足している可能性があります。このメソッド[representation metadata]は自動解放されたオブジェクトを返し、実行時にさらに自動解放されたオブジェクトを作成する可能性があります。これらのインスタンスはすべて自動解放プールに追加され、ARPがそれ自体を排出する機会を得たときに、最終的に解放される(およびそれらのメモリが解放される)のを待ちます。

問題は、コードが制御を実行ループに戻すまでこれが発生しないことです。したがって、ループの期間中、少なくとも600個の大きなディクショナリ(および場合によってはさらに多くのオブジェクト)が割り当てられ、割り当てが解除されません。これらのオブジェクトのサイズによっては、メモリ使用量が大幅に増加する可能性があります。

これは、ARCを使用しているかどうかに関係なく当てはまります。

この問題を回避するには、ループの反復ごとに新しい自動解放プールを作成してみてください。そうすれば、ARPは反復ごとに排出されます。

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

これは、パフォーマンスの観点からは必ずしも最善の解決策ではありませんが、少なくとも問題がメモリに関連しているかどうかはわかります。

PS:あなたのコードは今のところあまり意味がありません。同じアセットのメタデータを600回続けて取得するのはなぜですか?

于 2011-12-30T14:44:33.707 に答える
0

ここにコードを入力します。関連するアセットへのアクセスが完了するまで、ALAssetLibraryを保持していることを確認してください。Appleのドキュメントから:

ライブラリインスタンスから取得するオブジェクトの有効期間は、ライブラリインスタンスの有効期間に関連付けられています。

于 2011-12-30T16:56:40.983 に答える