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