5

私はARCプロジェクトを持っており、垂直線グラデーションを描画しようとしています。以下のコードはシミュレータで動作しますが、デバイス上でテストするとメモリ/ EXC_BAD_ACCESSエラーがスローされます。 (参考のために提供される)コードのARCを使用してグラデーションを描画するときのCFArrayRefとNSArrayの問題

NSArray *colorArray = [NSArray arrayWithObjects:(__bridge id)topColor, (__bridge id)bottomColor, nil]; 
CGGradientRef gradient = CGGradientCreateWithColors(colorSpace, (__bridge CFArrayRef) colorArray, colorLocations); 

これらの2行は、次のコードから取られる:アプリケーションがコードの次の2行とにクラッシュ

- (void)drawRect:(CGRect)rect 
{ 
    CGContextRef context = UIGraphicsGetCurrentContext(); 

    [self createGradientForContext:context andView:self.captionView]; 
    [self createGradientForContext:context andView:self.linksView]; 
    [self createGradientForContext:context andView:self.commentView]; 

} 

- (void)createGradientForContext:(CGContextRef)context andView:(UIView *)view 
{ 

    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); 

    CGFloat colorLocations[] = { 0.0f, 1.0f }; 

    CGColorRef topColor = [[UIColor colorWithRed:51.0f/255.0f green:51.0f/255.0f blue:51.0f/255.0f alpha:1.0f] CGColor]; 
    CGColorRef bottomColor = [[UIColor colorWithRed:48.0f/255.0f green:48.0f/255.0f blue:48.0f/255.0f alpha:1.0f] CGColor]; 
    NSArray *colorArray = [NSArray arrayWithObjects:(__bridge id)topColor, (__bridge id)bottomColor, nil]; 
    CGGradientRef gradient = CGGradientCreateWithColors(colorSpace, (__bridge_retained CFArrayRef) colorArray, colorLocations);  

    CGRect frame = view.frame; 
    CGPoint startPoint = CGPointMake(CGRectGetMidX(frame), CGRectGetMinY(frame)); 
    CGPoint endPoint = CGPointMake(CGRectGetMidX(frame), CGRectGetMaxY(frame)); 

    CGContextSaveGState(context); 
    CGContextAddRect(context, frame); 
    CGContextClip(context); 
    CGContextDrawLinearGradient(context, gradient, startPoint, endPoint, 0); 
    CGContextRestoreGState(context); 

    CGGradientRelease(gradient); 
    CGColorSpaceRelease(colorSpace); 

} 

おかげを前もって任意およびすべてのガイダンス。

+0

アークが好きではないですか?プログラマがメモリを制御することをやめて...私は、Appleがガベージコレクションの教訓を学んだと思った。私はそれを使用しないことをお勧めします... –

+3

私はARCを使用することをお勧めします、本当に魅力的な理由にする必要があります。 – zaph

+0

他のすべてが 'CFType'のときにオブジェクトを使用しているのはなぜですか? 'CFArray'を使うだけで、ブリッジを心配する必要はありません。 –

答えて

5

CFArrayRefを試してみてください。ブリッジを回避し、違いがあるかどうかを確認してください。今

CGFloat topColorComps[] = {51.0f/255.0f, 51.0f/255.0f, 51.0f/255.0f, 1.0f}; 
CGFloat bottomColorComps[] = {48.0f/255.0f, 48.0f/255.0f, 48.0f/255.0f, 1.0f};    

CGColorSpaceRef rgb = CGColorSpaceCreateDeviceRGB(); 
CGColorRef topColor = CGColorCreate(rgb, topColorComps); 
CGColorRef bottomColor = CGColorCreate(rgb, bottomColorComps); 
CGColorSpaceRelease(rgb); 

CFMutableArrayRef colorArray = CFArrayCreateMutable(NULL, 2, &kCFTypeArrayCallbacks); 
CFArrayAppendValue(colorArray, topColor); 
CFArrayAppendValue(colorArray, bottomColor); 

CGGradientRef gradient = CGGradientCreateWithColors(colorSpace, colorArray, colorLocations); 

CFRelease(colorArray); 
CFRelease(topColor); 
CFRelease(bottomColor); 
+0

あなたの助けをありがとう。残念ながら、私のデバイスでCFlrayAppendValue(colorArray、topColor)を実行しているときにクラッシュします。 – ArtSabintsev

+0

@ArtSabintsev:この問題は 'UIColor'の使用になります。上記の例を編集しましたが、今回はすべてを所有しています。 – dreamlax

+0

ありがとう!今では 'CGColorCreateGenericRGB is unavailable'を取得しています。これを見てください。 – ArtSabintsev

7

あなたがクラッシュした理由を説明する...

問題は、これらの2つの行です:これは非常に共通の問題である

CGColorRef topColor = [[UIColor colorWithRed:51.0f/255.0f green:51.0f/255.0f blue:51.0f/255.0f alpha:1.0f] CGColor]; 
CGColorRef bottomColor = [[UIColor colorWithRed:48.0f/255.0f green:48.0f/255.0f blue:48.0f/255.0f alpha:1.0f] CGColor]; 

。スタックオーバーフローについては、これで噛まれたユーザーから多くの質問があります。

問題は、これらのUIColorオブジェクトがこれらの行の後で参照されないため、ARCが直ちにそれらを解放し、それらのUIColorオブジェクトがCGColorオブジェクトの唯一の所有者であるため、UIColorsがCGColorsを直ちに解放し、 CGColorオブジェクト。次に配列に入れようとします。

NSArrayから純粋なCFArrayに切り替えることはこれを解決しません。 UIColorから純粋なCGColorへの切り替えは1つの解決策です。もう1つはCGColorsにあなた自身の所有権を置くことです:

CGColorRef topColor = CGColorRetain([[UIColor colorWithRed:51.0f/255.0f green:51.0f/255.0f blue:51.0f/255.0f alpha:1.0f] CGColor]); 
CGColorRef bottomColor = CGColorRetain([[UIColor colorWithRed:48.0f/255.0f green:48.0f/255.0f blue:48.0f/255.0f alpha:1.0f] CGColor]); 

⋮ 

CGColorRelease(topColor); 
CGColorRelease(bottomColor); 
+3

+1にする必要があります。私にとって、より良い解決策は、配列を作成するまでUIColorを使用することです: [NSArray arrayWithObjects:(__ bridge id)startColour.CGColor、(__bridge id)endColour.CGColor、nil]; – Cthutu

+0

@Cthutu:それはあなた自身を保持することと効果的に同じです。その場合、配列はそれらを保持します。非勾配の目的のために 'myUIColor.CGColor'を直接' CGContextSetFillColorWithColor'またはそれに似たもの( 'CGColorRef'変数で隠してから取り出すのではなく、そこから取得するのではなく)を渡すのは、その関数がカラーオブジェクトそれを維持しようとしません。 –

+0

はい、まったく同じことですが、CGColorRelease()をすべて呼び出す必要はありません。このリリースは、Core FoundationコールではなくARCで行われます。 – Cthutu

関連する問題