2014-03-04 8 views
2

드로잉에 CGlayers을 사용하고 있습니다. 설명서에 나와 있듯이 캔버스에서 드로잉을 렌더링하는 것이 더 효율적입니다.CGlayer 드로잉의 성능이 느림

I 기본적 CGlayers에 그릴과는 CGContextDrawLayerInRect 여기

를 사용하여 그래픽 콘텍스트에 층을 그리는 제의 drawRect 방법

기능 함수 이전 내 접촉에서
- (void)drawRect:(CGRect)rect 
{  
    switch (m_drawStep) 
    { 
     case DRAW: 
     {    
      CGContextRef context = UIGraphicsGetCurrentContext();//Get a reference to current context(The context to draw) 

      if(self.currentDrawingLayer == nil)//Potential leak of memory- static analyzer 
      { 
       CGFloat scale = self.contentScaleFactor; 
       CGRect bounds = CGRectMake(0, 0, self.bounds.size.width * scale, self.bounds.size.height * scale); 
       CGLayerRef layer = CGLayerCreateWithContext(context, bounds.size, NULL); 
       CGContextRef layerContext = CGLayerGetContext(layer); 
       CGContextScaleCTM(layerContext, scale, scale); 
       self.currentDrawingLayer = layer; 
      }   

      CGContextRef layerContext = CGLayerGetContext(self.currentDrawingLayer);//Potential leak of memory- static analyzer 
      CGContextBeginPath(layerContext); 
      CGContextAddPath(layerContext, mutablePath); 
      CGContextSetLineWidth(layerContext, self.lineWidth); 
      CGContextSetStrokeColorWithColor(layerContext, self.lineColor.CGColor); 
      CGContextSetFillColorWithColor(layerContext, self.lineColor.CGColor); 
      CGContextSetBlendMode(layerContext,kCGBlendModeNormal); 
      CGContextStrokePath(layerContext); 
      CGPathRelease(mutablePath); 

      CGContextDrawLayerInRect(context, self.bounds, self.currentDrawingLayer);//Potential leak of memory- static analyzer 
     } 
      break; 

     case UNDO: 
     {       
      CGContextRef context = UIGraphicsGetCurrentContext();   

      if(self.currentDrawingLayer == nil)//Potential leak of memory- static analyzer 
      { 
       CGFloat scale = self.contentScaleFactor; 
       CGRect bounds = CGRectMake(0, 0, self.bounds.size.width * scale, self.bounds.size.height * scale); 
       CGLayerRef layer = CGLayerCreateWithContext(context, bounds.size, NULL); 
       CGContextRef layerContext = CGLayerGetContext(layer); 
       CGContextScaleCTM(layerContext, scale, scale); 
       self.currentDrawingLayer = layer; 
      }         

      CGContextRef layerContext1 = CGLayerGetContext(self.currentDrawingLayer);//Potential leak of memory- static analyzer 
      CGContextClearRect(layerContext1, self.bounds); 

      for(NSArray *undoArray in m_parentUndoArray) 
      { 
       for(int i =0; i<[undoArray count];i++) 
       { 
        DrawingPath *drawPath = [undoArray objectAtIndex:i]; 
        CGPathRef path = drawPath.path.CGPath; 
        mutablePath = CGPathCreateMutableCopy(path); 


        CGContextBeginPath(layerContext1); 
        CGContextAddPath(layerContext1, mutablePath); 
        CGContextSetLineWidth(layerContext1, drawPath.pathWidth.floatValue); 
        CGContextSetStrokeColorWithColor(layerContext1, drawPath.pathColor.CGColor); 

        if([drawPath.pathColor isEqual:[UIColor clearColor]]) 
        { 
         CGContextSetBlendMode(layerContext1,kCGBlendModeClear); 
        } 
        else 
        { 
         CGContextSetBlendMode(layerContext1,kCGBlendModeNormal); 
        } 

         CGContextStrokePath(layerContext1); 
         CGPathRelease(mutablePath); 
        } 
       } 

       CGContextDrawLayerInRect(context, self.bounds, self.currentDrawingLayer);//Potential leak of memory- static analyzer 
      } 
     } 
      break; 



    [super drawRect:rect]; 
} 

이고, I는 UIBezeirPath을 만들고 그것을 CGPath로 변환하십시오. 그리는 동안의 터치에

-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event 
{   
    self.currentPath = [[DrawingPath alloc] init]; 

    if(m_eraseButtonClicked) 
    { 
     [self.currentPath setPathColor:[UIColor clearColor]];   
    } 
    else 
    { 
     [self.currentPath setPathColor:self.lineColor];    
    } 

    CGPathRef cgPath = self.currentPath.path.CGPath; 
    mutablePath = CGPathCreateMutableCopy(cgPath); 

     [m_undoArray addObject:self.currentPath]; 
     [self setNeedsDisplay]; 

    } 

는 I 직면하고

-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event 
{ 
    [m_parentUndoArray addObject:[NSArray arrayWithArray:m_undoArray]]; 

} 

문제점은 I 타임 프로파일 테스트

1) 이하 끝난 CGContextDrawLayerInRect는 시간의 90 %로 얻어 그래서이 메서드로 찍은이 시간을 줄이고 drawRect 메서드를 최적화하는 방법을 알고 싶습니다.

2) 길게 보이는 선을 그리지 않고 연속적으로 실행 취소/다시 실행을 시작하면 CGContextDrawLayerInRect으로 많은 시간이 걸립니다.

3) 내가 그린 라인을 지우고 반복적으로 실행 취소/다시 실행을 시작하면 메모리 경고로 인해 앱이 다운되고 erase가 잘못되었다는 것을 알지 못한다.

편집 : 코드 정적 분석기는 메모리 문제가 내 자신의 실험에서

+0

누수 계측기로 메모리 누수를보고하는 계기는 있습니까? 좀비를 활성화 했습니까 (할당 해제 된 메모리가 실제로 할당 해제되지 않습니다)? 코드에서 Xcode의 정적 분석기를 실행하여 메모리 관리 관련 문제를보고했는지 확인 했습니까? – Gavin

+0

안녕하세요 @ Gavin, CoreGraphics 함수로 메모리 누수를보고합니다. 좀비에 대해 잘 모릅니다. 정적 분석기를 실행하지 않았습니다. – Ranjit

+0

정적 분석기를 실행했는데 업데이트 된 위의 코드 줄에서보고 된 문제가 있습니다. – Ranjit

답변

0

가 말한다 곳에 표시하도록 업데이트, 아이폰 OS 때때로 크기에 따라 CGContextDrawLayerInRect의 GPU 때로는 CPU를 사용하는 것으로 보인다 (그리고 잠재적으로 다른 요인들). CPU를 사용할 때 속도는 20 배 느립니다.

해결 방법 유일한 해결책은 setNeedsDisplay 대신 setNeedsDisplayInRect를 사용하고 drawRect 코드에서 CGContextClipToRect (context, rect)를 추가하여 업데이트 된 영역의 크기를 줄이는 것입니다.