2013-02-13 54 views
1

我有一個自定義的UIView,它是一個帶圓角矩形的陰影和一個小邊框。CGContextSetShadowWithColor在設備上沒有顯示

- (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

您是否嘗試過更大的陰影? – Larme 2013-02-13 16:18:11

+0

是的,我嘗試過,無論我做得有多大,它都會顯示在設備上,甚至嘗試使用紅色。 – FrankWest 2013-02-13 16:22:46

+0

你是否在超越界限?即被剪切的影子? – 2013-02-13 16:26:33

回答

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); 
+0

謝謝你的不錯的和詳細的解釋。我不知道ARC不知道如何處理CF對象,儘管我總是懷疑ARC在這個「魔術」下做了什麼。 – FrankWest 2013-02-13 21:15:08

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]; 

}

相關問題