2009-08-18 7 views
0

이 오히려 간단한 예입니다 아마 어쨌든 많은 차이를하지,하지만 내가 그라데이션 그리기 뷰에서이 도면 코드가 있다고 가정 해 :이 매우 무시할 예를 실감-drawRect :에 대한 일반적인 작업을 iPhone에 캐시해야합니까?

@interface SomeView : UIView 
@end 

@implementation SomeView 

- (void)drawRect:(CGRect)rect 
{ 
    const CGContextRef ctx = UIGraphicsGetCurrentContext(); 

    // Set fill color to white 
    CGContextSetGrayFillColor(ctx, 1.0f, 1.0f); 
    CGContextFillRect(ctx, rect); 

    // Create a fancy, albeit ugly, orange gradient 
    const CGColorSpaceRef rgbColorSpace = CGColorSpaceCreateDeviceRGB(); 
    const CGFloat components[] = { 1.0, 0.5, 0.4, 1.0, // Start color 
            0.8, 0.8, 0.3, 1.0 }; // End color 
    CGGradientRef gloss; 
    gloss = CGGradientCreateWithColorComponents(rgbColorSpace, components, NULL, 2); 
    CGColorSpaceRelease(rgbColorSpace); 

    // Draw the gradient 
    const CGPoint endPoint = {rect.origin.x, 
           rect.origin.y + floor(rect.size.height/2.0f)}; 
    CGContextDrawLinearGradient(ctx, gloss, rect.origin, endPoint, 0); 
    CGGradientRelease(gloss); 
} 

@end 

을 , 재사용 할 더 복잡한 가치가 있다면 당신은 그 염려를 상상할 수 있습니다. Cocoa-Touch를 캐쉬 할 필요가 있습니까? 아니면 Cocoa-Touch가 본질적으로 CALayers를 사용하여 수행합니까? 여기

내가 캐싱 무엇을 의미의 예 : 당신은 분명히 균형을 여기에서 볼 수 있습니다

@interface SomeView : UIView 
{ 
    CGGradientRef gloss; 
} 
@end 

@implementation SomeView 

- (id)initWithFrame:(CGRect)frame 
{ 
    if (self = [super initWithFrame:frame]) { 
     // Create a fancy, albeit ugly, orange gradient only once here instead 
     const CGColorSpaceRef rgbColorSpace = CGColorSpaceCreateDeviceRGB(); 
     const CGFloat components[] = { 1.0, 0.5, 0.4, 1.0, // Start color 
             0.8, 0.8, 0.3, 1.0 }; // End color 
     CGGradientRef gloss; 
     gloss = CGGradientCreateWithColorComponents(rgbColorSpace, components, NULL, 2); 
     CGColorSpaceRelease(rgbColorSpace); 
    } 
    return self; 
} 

- (void)dealloc 
{ 
    CGGradientRelease(gradient); 
    [super dealloc]; 
} 

- (void)drawRect:(CGRect) 
{ 
    const CGContextRef ctx = UIGraphicsGetCurrentContext(); 

    // Set fill color to white 
    CGContextSetGrayFillColor(ctx, 1.0f, 1.0f); 
    CGContextFillRect(ctx, rect); 

    // Draw the gradient 
    const CGPoint endPoint = {rect.origin.x, 
           rect.origin.y + floor(rect.size.height/2.0f)}; 
    CGContextDrawLinearGradient(ctx, gloss, rect.origin, endPoint, 0); 
} 

@end 

; 특히 이러한 견해가 많으면이 기법으로 더 많은 메모리를 사용하게 될 수도 있고 이전 기법에서 드로잉 성능을 저하시킬 수도 있습니다. 그러나, 심지어 인 지 모르겠다. 왜냐하면 나는 코코아가 어떤 마법을 부리는 지 알지 못하기 때문이다. 아무도 설명 할 수 있을까요?

답변

1

"캐시 된"유일한 메시지는 drawRect: 메시지의 결과입니다. 무효화 될 때까지 캐시되고,이 경우 메시지가 다시 호출됩니다.

코코아 및 Cocoa-Touch는 메서드에서 사용하는 개체를 캐시하지 않습니다. 두 번째 예제에서와 마찬가지로 직접 캐시 할 수 있습니다. 그러나 인스트루먼트와 같은 프로파일 러를 사용하여 그러한 최적화를 테스트하는 것이 좋습니다. 코드를 복잡하게 만들지 않아도됩니다.

+0

언제 무효화됩니까? – Michael

+0

+1 무효화 될 때 많은 것들이 그것을 무효화 할 수 있으며 뷰의 일부만 무효화 할 수 있습니다 (즉, -drawRect : CGRect를 전달하여 무효화 된 부분을 알려줍니다). -setNeedsDisplay를 호출하면 물론 무효화됩니다. 보기가 화면에 나타날 때. 보기의 "상태"가 변경 될 때 (예를 들어 강조 표시). 뷰의 크기가 변경 될 때 때때로 스크롤하는 동안 (비트 맵 캐시 최적화가 있지만). –

+0

더 많은 논평에서, 애플은 당신이 그것을 도울 수있는 경우 그라디언트 그리기를 권장하지 않습니다. iPhone이 항상 빠르지는 않습니다. Apple의 추천은 이미지를 사용하는 것입니다. 그라디언트는 종종 단일 픽셀 너비의 이미지로 처리되며 가로 세로로 늘어나 원하는 영역을 채 웁니다. –

0

각 UIView에는 자체의 오프 스크린 드로잉 버퍼가 있으므로 움직입니다 주위의 UIView 또는 가시성을 변경해도 UIView가 다시 그려지지 않습니다. 이미 언급했듯이 다시 그리기를 트리거하는 특정 인스턴스가 있지만, 이러한 인스턴스가 발생하지 않는 한 drawRect 루틴을 호출해서는 안됩니다. (실험으로, 호출 될 때 NSLog 호출로 drawRect 루틴을 시작해보십시오.) 그리기가 실제로 실행되는 횟수를 제한하여 드로잉을 "빠르게"만드는 단계를 한 단계 가까이 할 수 있습니다.

Shark와 같은 성능 측정 도구를 사용하여 그리기 루틴의 소요 시간과 그 중에서 가장 많은 시간을 차지하는 항목을 확인할 수 있어야합니다. 이 분석은 특히 실제로 그렇지 않을 때 비용이 많이 든다고 생각하는 것을 캐싱하지 못하게하므로 매우 적은 성능으로 시간과 복잡성을 유발할 수 있습니다.

관련 문제