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 Generation)时,它只呈现圆角矩形和边框,但没有阴影。有任何想法吗?

4

2 回答 2

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);
于 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 回答