1

角が丸いドロップシャドウと小さな境界線を持つ長方形であるカスタムUIViewがあります。

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

    //// Shadow Declarations
    CGColorRef shadow = [UIColor colorWithRed:0.0/255.0 green:0.0/255.0 blue:0.0/255.0 alpha:0.3].CGColor;
    CGSize shadowOffset = CGSizeMake(0, 1);
    CGFloat shadowBlurRadius = 2;

    //// Abstracted Graphic Attributes
    CGRect roundedRectangleFrame = CGRectMake(2, 0, rect.size.width - 4, rect.size.height - 2);


    //// Rounded Rectangle Drawing
    UIBezierPath* roundedRectanglePath = [UIBezierPath bezierPathWithRoundedRect: roundedRectangleFrame cornerRadius: 2];
    CGContextSaveGState(context);
    CGContextSetShadowWithColor(context, shadowOffset, shadowBlurRadius, shadow);
    [[UIColor whiteColor] setFill];
    [roundedRectanglePath fill];
    CGContextRestoreGState(context);

    [[UIColor colorWithRed:200.0/255.0 green:200.0/255.0 blue:200.0/255.0 alpha:0.3] setStroke];
    roundedRectanglePath.lineWidth = 0.5;
    [roundedRectanglePath stroke];
}

私の問題は、シミュレーターではすべてが完全にレンダリングされることですが、デバイスでコードを実行すると(iPod touch 4世代を使用)、角の丸い長方形と境界線のみがレンダリングされ、影はレンダリングされません。何か案は?

4

2 に答える 2

3

あなたはすでにあなたの解決策を見つけました、しかし私はあなたの元のコードがうまくいかなかった理由とあなたの解決策がうまくいく理由を説明します。

ARCを使用しています。つまり、コンパイラがObjective-Cオブジェクトの有効期間を自動的に管理します。ただし、コンパイラはCoreFoundationオブジェクトの存続期間を認識または管理していません。あなたの元のコードはこれを言います:

CGColorRef shadow = [UIColor colorWithRed:0.0/255.0 green:0.0/255.0 blue:0.0/255.0 alpha:0.3].CGColor;

を呼び出すと+[UIColor colorWithRed:green:blue:]、オブジェクトへの参照が返されUIColorます。すぐにCGColorメッセージをUIColorオブジェクトに送信し、を取得しCGColorRefます。

メソッドの後半でオブジェクトを使用しないためUIColor、コンパイラーはUIColor、そのステートメントの最後でオブジェクトをすぐに解放しても安全であると考えます。そこで解放すると、UIColor割り当てが解除されます。割り当てが解除されると、UIColorオブジェクトはオブジェクトを解放しCGColorます。オブジェクトの所有権を主張しなかったのでCGColor、そのリリースはCGColorオブジェクトの割り当てを解除します。CGContextSetShadowWithColorステートメントに到達するまでに、CGColorオブジェクトを含むメモリは不明な状態になっています。

ソリューションは、オブジェクト+[UIColor colorWithRed:green:blue:]を使用するステートメントにメッセージを埋め込むことで問題を修正しCGColorます。したがって、ステートメントが終了し、UIColorが解放されて割り当てが解除されるまでに、グラフィックコンテキストに既に引き渡されておりCGColor、グラフィックコンテキストがそれを保持し、割り当てが解除されるのを防ぎます。

それは私も問題を解決する方法です。しかし、他の方法があります。もう1つの方法は、CGColorオブジェクトの所有権を明示的に主張することです。

CGColorRef shadow = CGColorRetain([UIColor colorWithRed:0.0/255.0
    green:0.0/255.0 blue:0.0/255.0 alpha:0.3].CGColor);

...

CGContextSetShadowWithColor(context, shadowOffset, shadowBlurRadius, shadow);
CGColorRelease(shadow);
于 2013-02-13T20:09:31.903 に答える
1

理由はわかりませんが、UIColor式自体を使用してCGColorRefを使用する代わりに、問題を「解決」しました。これで、シミュレーターとデバイスのすべての解像度で完璧にレンダリングされます。

現在機能しているコードは次のようになります。

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

//// Shadow Declarations
CGSize shadowOffset = CGSizeMake(0, 1);
CGFloat shadowBlurRadius = 2;

//// Abstracted Graphic Attributes
CGRect roundedRectangleFrame = CGRectMake(2, 0, rect.size.width - 4, rect.size.height - 2);


//// Rounded Rectangle Drawing
UIBezierPath* roundedRectanglePath = [UIBezierPath bezierPathWithRoundedRect: roundedRectangleFrame cornerRadius: 2];
CGContextSaveGState(context);
CGContextSetShadowWithColor(context, shadowOffset, shadowBlurRadius, [UIColor colorWithRed:0.0/255.0 green:0.0/255.0 blue:0.0/255.0 alpha:0.3].CGColor);
[[UIColor whiteColor] setFill];
[roundedRectanglePath fill];
CGContextRestoreGState(context);

[[UIColor colorWithRed:200.0/255.0 green:200.0/255.0 blue:200.0/255.0 alpha:0.3] setStroke];
roundedRectanglePath.lineWidth = 0.5;
[roundedRectanglePath stroke];

}

于 2013-02-13T19:36:38.290 に答える