2012-02-21 4 views
5

자주 변경되는 일부 내용과 훨씬 드물게 변경되는 내용이있는 사용자 지정 NSView 개체를 만들고 있습니다. 그것이 나올 것이므로, 자주 변경되지 않는 부분은 그리는 데 가장 많은 시간이 걸립니다. 이 두 부분을 다른 레이어로 렌더링하여 하나 또는 다른 부분을 개별적으로 업데이트 할 수 있으므로 사용자 인터페이스가 부진합니다.CALayer를 사용하여 뷰 렌더링 속도를 높일 수 있습니까?

어떻게해야합니까? 이런 종류의 좋은 튜토리얼을 많이 찾지 못했고 CALayer에 NSBezierPaths를 렌더링하는 방법에 대해서도 이야기하지 않았습니다. 누구 아이디어?

답변

4

당신의 직감이 옳습니다. 실제로 이것은 그림을 최적화하는 훌륭한 방법입니다. 요소가 맨 위로 이동했을 때 다시 그려지는 것을 피하고 싶었던 정적 인 배경이있는 곳에서는 직접 해본 적이 있습니다.

보기에 각 콘텐츠 항목에 대해 CALayer 개의 개체를 추가하기 만하면됩니다. 레이어를 그리려면 뷰를 각 레이어의 위임자로 설정 한 다음 drawLayer:inContext: 메서드를 구현해야합니다. 당신이 층 중 하나의 컨텐츠를 업데이트 할 때 단지 [yourLayer setNeedsDisplay] 전화,

- (void)drawLayer:(CALayer*)layer inContext:(CGContextRef)ctx 
{ 
    if(layer == yourBackgroundLayer) 
    { 
     //draw your background content in the context 
     //you can either use Quartz drawing directly in the CGContextRef, 
     //or if you want to use the Cocoa drawing objects you can do this: 
     NSGraphicsContext* drawingContext = [NSGraphicsContext graphicsContextWithGraphicsPort:ctx flipped:YES]; 
     NSGraphicsContext* previousContext = [NSGraphicsContext currentContext]; 
     [NSGraphicsContext setCurrentContext:drawingContext]; 
     [NSGraphicsContext saveGraphicsState]; 
     //draw some stuff with NSBezierPath etc 
     [NSGraphicsContext restoreGraphicsState]; 
     [NSGraphicsContext setCurrentContext:previousContext]; 
    } 
    else if (layer == someOtherLayer) 
    { 
     //draw other layer 
    } 
    //etc etc 
} 

:

그 방법 당신은 각 층의 내용을 그립니다. 그러면 위의 위임 메서드가 호출되어 업데이트 된 레이어 내용을 제공합니다.

기본적으로 레이어 내용을 변경하면 Core Animation은 새 내용에 대한 훌륭한 페이드 전환 효과를 제공합니다. 그러나 드로잉을 직접 처리하는 경우 레이어 콘텐츠가 변경 될 때 애니메이션의 기본 페이드를 방지하려면 actionForLayer:forKey: 대리자 메서드를 구현하고 null 액션 :

- (id<CAAction>)actionForLayer:(CALayer*)layer forKey:(NSString*)key 
{ 
    if(layer == someLayer) 
    { 
     //we don't want to animate new content in and out 
     if([key isEqualToString:@"contents"]) 
     { 
      return (id<CAAction>)[NSNull null]; 
     } 
    } 
    //the default action for everything else 
    return nil; 
} 
+0

감사합니다. 매우 도움이됩니다. 그러나 위임 메서드를 실행하는 데 문제가 있습니다. 내 뷰를 대리인으로 설정하고 루트 레이어의 하위 레이어로 레이어를 추가하고'setNeedsDisplay'를 호출하지만 drawLayer : inContext는 호출되지 않습니다. 어떤 아이디어? – mtmurdock

+0

코드를 게시 할 수 있습니까? 이것은 효과가있다. –

+0

나는 또한'drawRect :'를 오버라이드하여 다른 함수를 호출하지 못하게 할 수 있습니까? – mtmurdock