2013-02-13 2 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]; 
} 

내 문제는 시뮬레이터에 모든 것이 완벽하게 렌더링되는 것입니다하지만이 장치에서 코드를 실행하면 (나는 아이팟 터치 4 세대를 사용). 어떤 아이디어?

+0

더 큰 그림자로 시도 했습니까? – Larme

+0

네, 장치에 얼마나 큰지 확인해 보았습니다. 빨강 색을 사용해 보았습니다. – FrankWest

+0

경계선을 벗어 났습니까? 나는. 그림자가 잘린거야? –

답변

3

당신은 이미 해결책을 발견하지만, 원래의 코드가 작동 왜 솔루션이 작동하지 않은 이유를 설명 할 것이다.

ARC를 사용하고 있습니다. 즉, 컴파일러가 자동으로 Objective-C 객체의 수명을 관리합니다. 그러나 컴파일러는 Core Foundation 객체의 수명을 알지 못하거나 관리하지 않습니다. 당신이 +[UIColor colorWithRed:green:blue:]를 호출 할 때

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

는, 그것이 UIColor 객체에 대한 참조를 반환 : 원래 코드는이 말한다. CGColor 메시지를 즉시 UIColor 개체로 보내면 CGColorRef이됩니다.

나중에 메서드에서 UIColor 개체를 사용하지 않으므로 컴파일러는 해당 문 끝에서 UIColor 개체를 즉시 해제하는 것이 안전하다고 생각합니다. UIColor을 릴리스하면 할당이 해제됩니다. 할당이 해제되면 UIColor 개체가 CGColor 개체를 해제합니다. CGColor 개체의 소유권을 주장하지 않았으므로이 릴리스는 CGColor 개체의 할당을 해제합니다. CGContextSetShadowWithColor 문을 사용하면 CGColor 개체가 포함 된 메모리를 알 수없는 상태가됩니다.

CGColor 개체를 사용하는 문에 +[UIColor colorWithRed:green:blue:] 메시지를 포함 시켜서 문제를 해결할 수 있습니다. 따라서 문이 끝나고 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

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

}

관련 문제