2014-03-04 152 views
2

我正在使用CGlayers用於繪圖,正如文檔所述,它是在畫布上繪製繪圖的更高效的方法。CGlayer繪圖性能低下

我基本上拉入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]; 
} 

以我的觸摸已移至函數功能,我創建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]; 

    } 

在觸摸結束

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

} 

其中,我所面臨的問題是以下

1)I與時間探查測試,CGContextDrawLayerInRect,需要90%的時間,同時繪製,所以我想知道如何減少這種方法所花費的時間並優化drawRect方法。 2)如果我畫幾條冗長的線並開始不斷地撤消/重做,那麼你也可以看到CGContextDrawLayerInRect這需要很多時間。 3)如果我刪除了一些畫線並重復進行撤消/重做,更糟糕的是,我的應用程序崩潰了內存警告,我不知道擦除出了什麼問題,它花費了太多內存。

編輯:代碼,更新,以顯示在靜態分析說,他們是內存問題

+0

Is Instruments是否報告泄漏儀器存在任何內存泄漏?你有殭屍啓用(這將導致釋放內存永遠不會被釋放)?您是否在代碼中使用Xcode中的靜態分析器來查看它是否報告了有關內存管理的任何問題? – Gavin

+0

你好@Gavin,它報告與CoreGraphics功能的內存泄漏,我不知道殭屍,我沒有運行任何靜態分析器 – Ranjit

+0

我運行靜態分析器,其報告的問題在上面的代碼行,我已更新。 – Ranjit

回答

0

從我自己的實驗,看來iOS的有時會使用GPU,有時CPU進行CGContextDrawLayerInRect,根據大小被複制的圖層(以及潛在的其他因素)。當它使用CPU時,速度要慢20倍。

唯一的解決方法是通過使用setNeedsDisplayInRect而不是setNeedsDisplay,並在drawRect代碼中添加CGContextClipToRect(context,rect)來減小更新區域的大小。