5

私ははるかに複雑なプロジェクトの簡単なテストを試みていますが、以下のコードがクラッシュしてEXC_BAD_ACCESSエラーが発生する理由について困惑していますか?

これはUIViewから呼び出されます。

 - (void)testing {
      NSString *imagePath = [[NSBundle mainBundle] pathForResource:@"ball.png" ofType:nil];
      CGImageRef imageRef = [[[UIImage alloc]initWithContentsOfFile:imagePath]CGImage];
 //   CGImageRetain(imageRef);

      UIImage *newImage = [[UIImage alloc]initWithCGImage:imageRef];
      UIImageView *iv = [[UIImageView alloc]initWithImage:newImage];
      [self addSubview:iv];
 }

私の推測では、CGImageRefは保持されていませんが、CGImageRetain(imageRef);を追加しています。違いはありません。

また、このプロジェクトではARCがオンになっていることにも注意してください。

編集

もう少しテストを行ったところ、上記のコードのみを含む2つの基本的なプロジェクトを作成したため、これがARCに直接関係していることがわかりました。最初のARCはオフになっていて、完全に機能しました。次のARCがオンになり、BAMが同じエラーでクラッシュします。興味深いのは、クラッシュする前にプロジェクトを初めて実行したときにのみ、実際のログエラーが発生したことです。

 Error: ImageIO: ImageProviderCopyImageBlockSetCallback 'ImageProviderCopyImageBlockSetCallback' header is not a CFDictionary...
4

2 に答える 2

13

この行が問題です:

CGImageRef imageRef = [[[UIImage alloc]initWithContentsOfFile:imagePath]CGImage];

作成されたUIImageは、この完全な式の直後 (たとえば、この行の後) に解放されます。そのため、後で追加しようとしても機能しCGImageRetain()ません。

根本的な問題は、CGImageRefから返されたCGImageがほぼ確実に のivar であり、 が割り当て解除UIImageされると解放されることUIImageです。

これを修正する一般的な方法は、UIImage. これを行うには、 をローカル変数に配置しUIImage、最後に を参照した後に参照しますCGImage(例: を使用(void)uiimageVar)。CGImageRefまたは、次のように、同じ行に を保持することもできます。

CGImageRef imageRef = CGImageRetain([[[UIImage alloc] initWithContentsOfFile:imagePath] CGImage]);

ただし、これを行う場合は、完了したらリリースすることを忘れないでくださいimageRef

于 2012-10-06T03:11:12.490 に答える
5

あなたはこれを書きました:

CGImageRef imageRef = [[[UIImage alloc]initWithContentsOfFile:imagePath]CGImage];

その行は を作成しUIImage、そのCGImageプロパティを取得してから、オブジェクトを解放しUIImageます。その行で を保持していないためCGImage、 の唯一の所有者はCGImageですUIImage。したがって、UIImageが解放されてすぐに割り当てが解除されると、 も割り当てが解除されますCGImage

がリリースさCGImageれる前にを保持する必要があります。UIImageこれを試して:

CGImageRef imageRef = CGImageRetain([[UIImage alloc]initWithContentsOfFile:imagePath].CGImage);

そして、関数の最後に:

CGImageRelease(imageRef);
于 2012-10-06T03:10:37.767 に答える