CGContextSetShadowWithColor未在设备上显示

时间:2013-02-13 16:03:38

标签: ios core-graphics

我有一个自定义的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代)时,它只呈现圆角矩形和边框但没有阴影。有什么想法吗?

2 个答案:

答案 0 :(得分:3)

您已经找到了解决方案,但我会解释您原始代码无效的原因以及解决方案的原因。

您正在使用ARC,这意味着编译器会自动为您管理Objective-C对象的生命周期。但是编译器不知道或管理Core Foundation对象的生命周期。您的原始代码说明了这一点:

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关闭到图形上下文,图形上下文保留它,防止它被释放。

这也是我解决这个问题的方法。但还有其他方法。另一种方法是明确声明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);

答案 1 :(得分: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];

}